brut 0.9.2 → 0.11.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/Gemfile.lock +15 -15
- data/assets/YouTubeThumb.pxd +0 -0
- data/bin/new-version +3 -3
- data/brut-css/package-lock.json +2 -2
- data/brut-css/package.json +1 -1
- data/brut-js/package-lock.json +2 -2
- data/brut-js/package.json +1 -1
- data/brut-js/specs/ConstraintViolationMessages.spec.js +4 -1
- data/brut-js/specs/Form.spec.js +2 -46
- data/brut-js/src/ConstraintViolationMessage.js +17 -2
- data/brut-js/src/Form.js +19 -23
- data/brutrb.com/.vitepress/config.mjs +1 -0
- data/brutrb.com/form-constraints.md +6 -6
- data/brutrb.com/getting-started.md +3 -0
- data/brutrb.com/images/tutorial/02-confirmation-dialog-browser-element-styled.png +0 -0
- data/brutrb.com/images/tutorial/02-confirmation-dialog-browser-element.png +0 -0
- data/brutrb.com/images/tutorial/02-confirmation-dialog-browser.png +0 -0
- data/brutrb.com/images/tutorial/02-confirmation-flow.graffle +0 -0
- data/brutrb.com/images/tutorial/02-confirmation-flow.png +0 -0
- data/brutrb.com/instrumentation.md +142 -3
- data/brutrb.com/recipes/form-errors.md +148 -0
- data/brutrb.com/tutorial.md +29 -1627
- data/brutrb.com/tutorials/01-intro.md +1630 -0
- data/brutrb.com/tutorials/02-dialog.md +569 -0
- data/docs/404.html +2 -2
- data/docs/adrs.html +4 -4
- data/docs/ai.html +4 -4
- data/docs/api/Brut/BackEnd/SeedData.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server/FlushSpans.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares.html +1 -1
- data/docs/api/Brut/BackEnd/Sidekiq.html +1 -1
- data/docs/api/Brut/BackEnd/Validators/FormValidator.html +1 -1
- data/docs/api/Brut/BackEnd/Validators.html +1 -1
- data/docs/api/Brut/BackEnd.html +1 -1
- data/docs/api/Brut/CLI/App.html +1 -1
- data/docs/api/Brut/CLI/AppRunner.html +1 -1
- data/docs/api/Brut/CLI/Apps/BuildAssets/All.html +1 -1
- data/docs/api/Brut/CLI/Apps/BuildAssets/CSS.html +1 -1
- data/docs/api/Brut/CLI/Apps/BuildAssets/Images.html +1 -1
- data/docs/api/Brut/CLI/Apps/BuildAssets/JS.html +1 -1
- data/docs/api/Brut/CLI/Apps/BuildAssets.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Create.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Drop.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Migrate.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/NewMigration.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Rebuild.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Seed.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB/Status.html +1 -1
- data/docs/api/Brut/CLI/Apps/DB.html +1 -1
- data/docs/api/Brut/CLI/Apps/DeployBase/GitChecks.html +1 -1
- data/docs/api/Brut/CLI/Apps/DeployBase.html +1 -1
- data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy/Deploy.html +1 -1
- data/docs/api/Brut/CLI/Apps/HerokuContainerBasedDeploy.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Action/Route.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Action.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Component.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/CustomElementTest.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/DbModel.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/E2ETest.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Form.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Page/Route.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Page.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/RoutesEditor.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold/Test.html +1 -1
- data/docs/api/Brut/CLI/Apps/Scaffold.html +1 -1
- data/docs/api/Brut/CLI/Apps/Test/Audit.html +1 -1
- data/docs/api/Brut/CLI/Apps/Test/E2e.html +1 -1
- data/docs/api/Brut/CLI/Apps/Test/JS.html +1 -1
- data/docs/api/Brut/CLI/Apps/Test/Run.html +1 -1
- data/docs/api/Brut/CLI/Apps/Test.html +1 -1
- data/docs/api/Brut/CLI/Apps.html +1 -1
- data/docs/api/Brut/CLI/Command.html +1 -1
- data/docs/api/Brut/CLI/Error.html +1 -1
- data/docs/api/Brut/CLI/ExecutionResults/Result.html +1 -1
- data/docs/api/Brut/CLI/ExecutionResults.html +1 -1
- data/docs/api/Brut/CLI/Executor.html +1 -1
- data/docs/api/Brut/CLI/InvalidOption.html +1 -1
- data/docs/api/Brut/CLI/Options.html +1 -1
- data/docs/api/Brut/CLI/Output.html +1 -1
- data/docs/api/Brut/CLI/SystemExecError.html +1 -1
- data/docs/api/Brut/CLI.html +1 -1
- data/docs/api/Brut/FactoryBot.html +1 -1
- data/docs/api/Brut/Framework/App.html +1 -1
- data/docs/api/Brut/Framework/Config.html +1 -1
- data/docs/api/Brut/Framework/Container.html +1 -1
- data/docs/api/Brut/Framework/Error.html +1 -1
- data/docs/api/Brut/Framework/Errors/AbstractMethod.html +1 -1
- data/docs/api/Brut/Framework/Errors/Bug.html +1 -1
- data/docs/api/Brut/Framework/Errors/MissingConfiguration.html +1 -1
- data/docs/api/Brut/Framework/Errors/MissingParameter.html +1 -1
- data/docs/api/Brut/Framework/Errors/NoClassForPath.html +1 -1
- data/docs/api/Brut/Framework/Errors/NotFound.html +1 -1
- data/docs/api/Brut/Framework/Errors/NotImplemented.html +1 -1
- data/docs/api/Brut/Framework/Errors.html +1 -1
- data/docs/api/Brut/Framework/FussyTypeEnforcement.html +1 -1
- data/docs/api/Brut/Framework/MCP.html +1 -1
- data/docs/api/Brut/Framework/ProjectEnvironment.html +1 -1
- data/docs/api/Brut/Framework.html +1 -1
- data/docs/api/Brut/FrontEnd/AssetPathResolver.html +1 -1
- data/docs/api/Brut/FrontEnd/Component/Helpers.html +1 -1
- data/docs/api/Brut/FrontEnd/Component.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/ConstraintViolations.html +48 -27
- data/docs/api/Brut/FrontEnd/Components/FormTag.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/I18nTranslations.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Input.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/CsrfToken.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/InputTag.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/RadioButton.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/SelectTagWithOptions.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs/TextareaTag.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Inputs.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/LocaleDetection.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/PageIdentifier.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/TimeTag.html +1 -1
- data/docs/api/Brut/FrontEnd/Components/Traceparent.html +1 -1
- data/docs/api/Brut/FrontEnd/Components.html +1 -1
- data/docs/api/Brut/FrontEnd/CsrfProtector.html +1 -1
- data/docs/api/Brut/FrontEnd/Download.html +1 -1
- data/docs/api/Brut/FrontEnd/Flash.html +1 -1
- data/docs/api/Brut/FrontEnd/Form.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/ConstraintViolation.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/Input/Color.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/Input/TimeOfDay.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/Input.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/InputDeclarations.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/InputDefinition.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInput.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInputDefinition.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/SelectInput.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/SelectInputDefinition.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms/ValidityState.html +1 -1
- data/docs/api/Brut/FrontEnd/Forms.html +1 -1
- data/docs/api/Brut/FrontEnd/GenericResponse.html +1 -1
- data/docs/api/Brut/FrontEnd/Handler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/CspReportingHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler/TraceParent.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/LocaleDetectionHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/MissingHandler/Form.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers/MissingHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Handlers.html +1 -1
- data/docs/api/Brut/FrontEnd/HandlingResults.html +1 -1
- data/docs/api/Brut/FrontEnd/HttpMethod.html +1 -1
- data/docs/api/Brut/FrontEnd/HttpStatus.html +1 -1
- data/docs/api/Brut/FrontEnd/InlineSvgLocator.html +1 -1
- data/docs/api/Brut/FrontEnd/Layout.html +1 -1
- data/docs/api/Brut/FrontEnd/Middleware.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/AnnotateBrutOwnedPaths.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/Favicon.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/OpenTelemetrySpan.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares/ReloadApp.html +1 -1
- data/docs/api/Brut/FrontEnd/Middlewares.html +1 -1
- data/docs/api/Brut/FrontEnd/Page.html +1 -1
- data/docs/api/Brut/FrontEnd/Pages/MissingPage.html +1 -1
- data/docs/api/Brut/FrontEnd/Pages.html +1 -1
- data/docs/api/Brut/FrontEnd/RequestContext.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHook.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/AgeFlash.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineScripts.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts/ReportOnly.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/LocaleDetection.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks/SetupRequestContext.html +1 -1
- data/docs/api/Brut/FrontEnd/RouteHooks.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/FormHandlerRoute.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/FormRoute.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingForm.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingHandler.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingPage.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/MissingPath.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/PageRoute.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing/Route.html +1 -1
- data/docs/api/Brut/FrontEnd/Routing.html +1 -1
- data/docs/api/Brut/FrontEnd/Session.html +1 -1
- data/docs/api/Brut/FrontEnd.html +1 -1
- data/docs/api/Brut/I18n/BaseMethods.html +1 -1
- data/docs/api/Brut/I18n/ForBackEnd.html +1 -1
- data/docs/api/Brut/I18n/ForCLI.html +1 -1
- data/docs/api/Brut/I18n/ForHTML.html +1 -1
- data/docs/api/Brut/I18n/HTTPAcceptLanguage/AlwaysEnglish.html +1 -1
- data/docs/api/Brut/I18n/HTTPAcceptLanguage.html +1 -1
- data/docs/api/Brut/I18n.html +1 -1
- data/docs/api/Brut/Instrumentation/LoggerSpanExporter.html +1 -1
- data/docs/api/Brut/Instrumentation/OpenTelemetry/NormalizedAttributes.html +1 -1
- data/docs/api/Brut/Instrumentation/OpenTelemetry/Span.html +1 -1
- data/docs/api/Brut/Instrumentation/OpenTelemetry.html +1 -1
- data/docs/api/Brut/Instrumentation.html +1 -1
- data/docs/api/Brut/RubocopConfig.html +1 -1
- data/docs/api/Brut/SinatraHelpers/ClassMethods.html +1 -1
- data/docs/api/Brut/SinatraHelpers.html +1 -1
- data/docs/api/Brut/SpecSupport/ClockSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/ComponentSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/E2ETestServer.html +1 -1
- data/docs/api/Brut/SpecSupport/E2eSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/EnhancedNode.html +1 -1
- data/docs/api/Brut/SpecSupport/FlashSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/GeneralSupport/ClassMethods.html +1 -1
- data/docs/api/Brut/SpecSupport/GeneralSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/HandlerSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/BeABug.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/BePageFor.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/BeRoutingFor.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveConstraintViolation.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveGenerated.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveHTMLAttribute.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveI18nString.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveLinkTo.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveRedirectedTo.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedHttpStatus.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers/HaveReturnedRackResponse.html +1 -1
- data/docs/api/Brut/SpecSupport/Matchers.html +1 -1
- data/docs/api/Brut/SpecSupport/RSpecSetup/OptionalSidekiqSupport.html +1 -1
- data/docs/api/Brut/SpecSupport/RSpecSetup.html +1 -1
- data/docs/api/Brut/SpecSupport/SessionSupport.html +1 -1
- data/docs/api/Brut/SpecSupport.html +1 -1
- data/docs/api/Brut.html +1 -1
- data/docs/api/Clock.html +1 -1
- data/docs/api/ModuleName.html +1 -1
- data/docs/api/RichString.html +1 -1
- data/docs/api/SemanticLogger/Appender/Async.html +1 -1
- data/docs/api/Sequel/Extensions/BrutInstrumentation.html +1 -1
- data/docs/api/Sequel/Extensions/BrutMigrations.html +1 -1
- data/docs/api/Sequel/Extensions.html +1 -1
- data/docs/api/Sequel/Plugins/CreatedAt/InstanceMethods.html +1 -1
- data/docs/api/Sequel/Plugins/CreatedAt.html +1 -1
- data/docs/api/Sequel/Plugins/ExternalId/ClassMethods.html +1 -1
- data/docs/api/Sequel/Plugins/ExternalId/InstanceMethods.html +1 -1
- data/docs/api/Sequel/Plugins/ExternalId.html +1 -1
- data/docs/api/Sequel/Plugins/FindBang/ClassMethods.html +1 -1
- data/docs/api/Sequel/Plugins/FindBang.html +1 -1
- data/docs/api/Sequel/Plugins.html +1 -1
- data/docs/api/Sequel.html +1 -1
- data/docs/api/_index.html +1 -1
- data/docs/api/file.README.html +1 -1
- data/docs/api/index.html +1 -1
- data/docs/api/top-level-namespace.html +1 -1
- data/docs/assets/02-confirmation-dialog-browser-element-styled.3NEGM20-.png +0 -0
- data/docs/assets/02-confirmation-dialog-browser-element.DPsf0xUW.png +0 -0
- data/docs/assets/02-confirmation-dialog-browser.DH8ALFO4.png +0 -0
- data/docs/assets/02-confirmation-flow.D9gZ0S5U.png +0 -0
- data/docs/assets/{app.DmIaHRc4.js → app.0-aKXKdt.js} +1 -1
- data/docs/assets/chunks/@localSearchIndexroot.DPhqaz1b.js +1 -0
- data/docs/assets/chunks/{VPLocalSearchBox.C2QeRbCY.js → VPLocalSearchBox.CW-UBkNA.js} +1 -1
- data/docs/assets/chunks/{theme.CFKmBRX5.js → theme.a6feKWJO.js} +2 -2
- data/docs/assets/{components.md.BBHib1uV.js → components.md.BzVRwegp.js} +3 -3
- data/docs/assets/{configuration.md.CJ0MmIps.js → configuration.md.eM5wFVi5.js} +1 -1
- data/docs/assets/{form-constraints.md.DK5adCgM.js → form-constraints.md.KTv5cdR4.js} +6 -6
- data/docs/assets/{forms.md.D5jFZIJz.js → forms.md.B3BHvCV3.js} +1 -1
- data/docs/assets/{getting-started.md.abLTnd_n.js → getting-started.md.BgR0ZHsl.js} +5 -2
- data/docs/assets/recipes_form-errors.md.Bv5RCKqH.js +66 -0
- data/docs/assets/recipes_form-errors.md.Bv5RCKqH.lean.js +1 -0
- data/docs/assets/tutorial.md.BM40jnoq.js +27 -0
- data/docs/assets/tutorial.md.BM40jnoq.lean.js +1 -0
- data/docs/assets/{tutorial.md.C4zR5XPG.js → tutorials_01-intro.md.BXvYWcO9.js} +5 -25
- data/docs/assets/tutorials_01-intro.md.BXvYWcO9.lean.js +1 -0
- data/docs/assets/tutorials_02-dialog.md.CIeg8R--.js +274 -0
- data/docs/assets/tutorials_02-dialog.md.CIeg8R--.lean.js +1 -0
- data/docs/assets.html +4 -4
- data/docs/brut-js/api/AjaxSubmit.html +1 -1
- data/docs/brut-js/api/AjaxSubmit.js.html +1 -1
- data/docs/brut-js/api/Autosubmit.html +1 -1
- data/docs/brut-js/api/Autosubmit.js.html +1 -1
- data/docs/brut-js/api/BaseCustomElement.html +1 -1
- data/docs/brut-js/api/BaseCustomElement.js.html +1 -1
- data/docs/brut-js/api/BrutCustomElements.html +1 -1
- data/docs/brut-js/api/BufferedLogger.html +1 -1
- data/docs/brut-js/api/ConfirmSubmit.html +1 -1
- data/docs/brut-js/api/ConfirmSubmit.js.html +1 -1
- data/docs/brut-js/api/ConfirmationDialog.html +1 -1
- data/docs/brut-js/api/ConfirmationDialog.js.html +1 -1
- data/docs/brut-js/api/ConstraintViolationMessage.html +55 -5
- data/docs/brut-js/api/ConstraintViolationMessage.js.html +18 -3
- data/docs/brut-js/api/ConstraintViolationMessages.html +1 -1
- data/docs/brut-js/api/ConstraintViolationMessages.js.html +1 -1
- data/docs/brut-js/api/CopyToClipboard.html +1 -1
- data/docs/brut-js/api/CopyToClipboard.js.html +1 -1
- data/docs/brut-js/api/Form.html +7 -10
- data/docs/brut-js/api/Form.js.html +20 -24
- data/docs/brut-js/api/I18nTranslation.html +1 -1
- data/docs/brut-js/api/I18nTranslation.js.html +1 -1
- data/docs/brut-js/api/LocaleDetection.html +1 -1
- data/docs/brut-js/api/LocaleDetection.js.html +1 -1
- data/docs/brut-js/api/Logger.html +1 -1
- data/docs/brut-js/api/Logger.js.html +1 -1
- data/docs/brut-js/api/Message.html +1 -1
- data/docs/brut-js/api/Message.js.html +1 -1
- data/docs/brut-js/api/PrefixedLogger.html +1 -1
- data/docs/brut-js/api/RichString.html +1 -1
- data/docs/brut-js/api/RichString.js.html +1 -1
- data/docs/brut-js/api/Tabs.html +1 -1
- data/docs/brut-js/api/Tabs.js.html +1 -1
- data/docs/brut-js/api/Tracing.html +1 -1
- data/docs/brut-js/api/Tracing.js.html +1 -1
- data/docs/brut-js/api/external-CustomElementRegistry.html +1 -1
- data/docs/brut-js/api/external-Performance.html +1 -1
- data/docs/brut-js/api/external-Promise.html +1 -1
- data/docs/brut-js/api/external-ValidityState.html +1 -1
- data/docs/brut-js/api/external-Window.html +1 -1
- data/docs/brut-js/api/external-fetch.html +1 -1
- data/docs/brut-js/api/global.html +1 -1
- data/docs/brut-js/api/index.html +1 -1
- data/docs/brut-js/api/index.js.html +1 -1
- data/docs/brut-js/api/module-testing.html +1 -1
- data/docs/brut-js/api/testing.AssetMetadata.html +1 -1
- data/docs/brut-js/api/testing.AssetMetadataLoader.html +1 -1
- data/docs/brut-js/api/testing.CustomElementTest.html +1 -1
- data/docs/brut-js/api/testing.DOMCreator.html +1 -1
- data/docs/brut-js/api/testing_AssetMetadata.js.html +1 -1
- data/docs/brut-js/api/testing_AssetMetadataLoader.js.html +1 -1
- data/docs/brut-js/api/testing_CustomElementTest.js.html +1 -1
- data/docs/brut-js/api/testing_DOMCreator.js.html +1 -1
- data/docs/brut-js/api/testing_index.js.html +1 -1
- data/docs/brut-js.html +4 -4
- data/docs/business-logic.html +4 -4
- data/docs/cli.html +4 -4
- data/docs/components.html +8 -8
- data/docs/configuration.html +5 -5
- data/docs/css.html +4 -4
- data/docs/custom-element-tests.html +4 -4
- data/docs/database-access.html +4 -4
- data/docs/database-schema.html +4 -4
- data/docs/deployment.html +4 -4
- data/docs/dev-environment.html +4 -4
- data/docs/dir-structure.html +4 -4
- data/docs/doc-conventions.html +4 -4
- data/docs/end-to-end-tests.html +4 -4
- data/docs/features.html +4 -4
- data/docs/flash-and-session.html +4 -4
- data/docs/form-constraints.html +11 -11
- data/docs/forms.html +6 -6
- data/docs/getting-started.html +10 -7
- data/docs/handlers.html +4 -4
- data/docs/hashmap.json +1 -1
- data/docs/hooks.html +4 -4
- data/docs/i18n.html +4 -4
- data/docs/index.html +3 -3
- data/docs/instrumentation.html +4 -4
- data/docs/javascript.html +4 -4
- data/docs/jobs.html +4 -4
- data/docs/keyword-injection.html +4 -4
- data/docs/layouts.html +4 -4
- data/docs/lsp.html +4 -4
- data/docs/markdown-examples.html +4 -4
- data/docs/middleware.html +4 -4
- data/docs/overview.html +4 -4
- data/docs/pages.html +4 -4
- data/docs/recipes/alternate-layouts.html +4 -4
- data/docs/recipes/authentication.html +5 -5
- data/docs/recipes/blank-layouts.html +4 -4
- data/docs/recipes/custom-flash.html +4 -4
- data/docs/recipes/form-errors.html +94 -0
- data/docs/recipes/indexed-forms.html +4 -4
- data/docs/recipes/migrations.html +5 -5
- data/docs/recipes/text-field-component.html +4 -4
- data/docs/roadmap.html +4 -4
- data/docs/routes.html +4 -4
- data/docs/security.html +4 -4
- data/docs/seed-data.html +4 -4
- data/docs/space-time-continuum.html +4 -4
- data/docs/tutorial.html +12 -713
- data/docs/tutorials/01-intro.html +736 -0
- data/docs/tutorials/02-dialog.html +302 -0
- data/docs/unit-tests.html +4 -4
- data/docs/why.html +4 -4
- data/lib/brut/front_end/components/constraint_violations.rb +23 -10
- data/lib/brut/instrumentation/methods.rb +153 -0
- data/lib/brut/instrumentation/open_telemetry.rb +1 -0
- data/lib/brut/instrumentation.rb +1 -0
- data/lib/brut/version.rb +1 -1
- data/mkbrut/Gemfile.lock +1 -1
- data/mkbrut/bin/publish +1 -1
- data/mkbrut/lib/mkbrut/version.rb +1 -1
- data/specs/brut/instrumentation/methods.spec.rb +399 -0
- metadata +40 -18
- data/.nvim.lua +0 -1
- data/docs/assets/chunks/@localSearchIndexroot.D0RGp49A.js +0 -1
- data/docs/assets/tutorial.md.C4zR5XPG.lean.js +0 -1
- /data/docs/assets/{components.md.BBHib1uV.lean.js → components.md.BzVRwegp.lean.js} +0 -0
- /data/docs/assets/{configuration.md.CJ0MmIps.lean.js → configuration.md.eM5wFVi5.lean.js} +0 -0
- /data/docs/assets/{form-constraints.md.DK5adCgM.lean.js → form-constraints.md.KTv5cdR4.lean.js} +0 -0
- /data/docs/assets/{forms.md.D5jFZIJz.lean.js → forms.md.B3BHvCV3.lean.js} +0 -0
- /data/docs/assets/{getting-started.md.abLTnd_n.lean.js → getting-started.md.BgR0ZHsl.lean.js} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c8a571939eb22e8583c8c44e8744565ef08cd08930fd3f378bc15ac245bc37da
|
4
|
+
data.tar.gz: 36fae7a408ca4a74d884e5fcc031e68920828bb17414d8b56bf9aff96df8c7e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e63645bd0090fb42de67b546b691cf2cf062da716938a8009db7caf556c613d64085fdc424c5d0c8d30f5edecb69aa58d6b273930309a221a56f36f8241cca49
|
7
|
+
data.tar.gz: db7fc64ad5d4b9615bd9217e73536a7c708a46ae1723841bc3fd2dfc524bee7a93b0e666533c4ed9ddbcbe0e86bcf8b6168c7146bed70a09fab32fbf87b59066
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Brut CHANGELOG
|
2
2
|
|
3
|
+
## v0.11.0 - Aug 27, 2025
|
4
|
+
|
5
|
+
* Added `Brut::Instrumentation::Methods` to allow instrumenting existing methods via `instrument`:
|
6
|
+
```ruby
|
7
|
+
class Widget
|
8
|
+
include Brut::Instrumentation::Methods
|
9
|
+
|
10
|
+
instrument def save
|
11
|
+
end
|
12
|
+
end
|
13
|
+
```
|
14
|
+
See docs for more options and details.
|
15
|
+
* When an exception is caught in a span, the span's status is set to an error.
|
16
|
+
|
17
|
+
## v0.10.0 - Aug 15, 2025
|
18
|
+
|
19
|
+
* Changed `ConstraintViolations` HTML to indicate if a `<brut-cv>` is server-generated, even if it's generating client-side constraint. See #56.
|
20
|
+
* `<brut-form>` now requires that all `<brut-cv-messages>` have an `input-name`.
|
21
|
+
|
22
|
+
|
3
23
|
## v0.9.2 - Aug 14, 2025
|
4
24
|
|
5
25
|
* Updated Docker instructions for installing PostgreSQL client, due to ruby:3.4 image upgrading to Debian Trixie which removed something. See https://github.com/thirdtank/brut/issues/55
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
brut (0.
|
4
|
+
brut (0.11.0)
|
5
5
|
concurrent-ruby
|
6
6
|
i18n
|
7
7
|
irb
|
@@ -23,7 +23,7 @@ PATH
|
|
23
23
|
GEM
|
24
24
|
remote: https://rubygems.org/
|
25
25
|
specs:
|
26
|
-
activesupport (8.0.2)
|
26
|
+
activesupport (8.0.2.1)
|
27
27
|
base64
|
28
28
|
benchmark (>= 0.3)
|
29
29
|
bigdecimal
|
@@ -47,26 +47,26 @@ GEM
|
|
47
47
|
dotenv (3.1.8)
|
48
48
|
drb (2.2.3)
|
49
49
|
erb (5.0.2)
|
50
|
-
factory_bot (6.5.
|
50
|
+
factory_bot (6.5.5)
|
51
51
|
activesupport (>= 6.1.0)
|
52
52
|
faker (3.5.2)
|
53
53
|
i18n (>= 1.8.11, < 2)
|
54
|
-
google-protobuf (4.
|
54
|
+
google-protobuf (4.32.0)
|
55
55
|
bigdecimal
|
56
56
|
rake (>= 13)
|
57
|
-
google-protobuf (4.
|
57
|
+
google-protobuf (4.32.0-aarch64-linux-gnu)
|
58
58
|
bigdecimal
|
59
59
|
rake (>= 13)
|
60
|
-
google-protobuf (4.
|
60
|
+
google-protobuf (4.32.0-arm64-darwin)
|
61
61
|
bigdecimal
|
62
62
|
rake (>= 13)
|
63
|
-
google-protobuf (4.
|
63
|
+
google-protobuf (4.32.0-x86-linux-gnu)
|
64
64
|
bigdecimal
|
65
65
|
rake (>= 13)
|
66
|
-
google-protobuf (4.
|
66
|
+
google-protobuf (4.32.0-x86_64-darwin)
|
67
67
|
bigdecimal
|
68
68
|
rake (>= 13)
|
69
|
-
google-protobuf (4.
|
69
|
+
google-protobuf (4.32.0-x86_64-linux-gnu)
|
70
70
|
bigdecimal
|
71
71
|
rake (>= 13)
|
72
72
|
googleapis-common-protos-types (1.20.0)
|
@@ -99,7 +99,7 @@ GEM
|
|
99
99
|
racc (~> 1.4)
|
100
100
|
nokogiri (1.18.9-x86_64-linux-gnu)
|
101
101
|
racc (~> 1.4)
|
102
|
-
opentelemetry-api (1.
|
102
|
+
opentelemetry-api (1.6.0)
|
103
103
|
opentelemetry-common (0.22.0)
|
104
104
|
opentelemetry-api (~> 1.0)
|
105
105
|
opentelemetry-exporter-otlp (0.30.0)
|
@@ -111,7 +111,7 @@ GEM
|
|
111
111
|
opentelemetry-semantic_conventions
|
112
112
|
opentelemetry-registry (0.4.0)
|
113
113
|
opentelemetry-api (~> 1.1)
|
114
|
-
opentelemetry-sdk (1.8.
|
114
|
+
opentelemetry-sdk (1.8.1)
|
115
115
|
opentelemetry-api (~> 1.1)
|
116
116
|
opentelemetry-common (~> 0.20)
|
117
117
|
opentelemetry-registry (~> 0.2)
|
@@ -149,7 +149,7 @@ GEM
|
|
149
149
|
rdoc (6.14.2)
|
150
150
|
erb
|
151
151
|
psych (>= 4.0.0)
|
152
|
-
regexp_parser (2.11.
|
152
|
+
regexp_parser (2.11.2)
|
153
153
|
reline (0.6.2)
|
154
154
|
io-console (~> 0.5)
|
155
155
|
rspec (3.13.1)
|
@@ -164,8 +164,8 @@ GEM
|
|
164
164
|
rspec-mocks (3.13.5)
|
165
165
|
diff-lcs (>= 1.2.0, < 2.0)
|
166
166
|
rspec-support (~> 3.13.0)
|
167
|
-
rspec-support (3.13.
|
168
|
-
rubocop (1.
|
167
|
+
rspec-support (3.13.5)
|
168
|
+
rubocop (1.80.1)
|
169
169
|
json (~> 2.3)
|
170
170
|
language_server-protocol (~> 3.17.0.2)
|
171
171
|
lint_roller (~> 1.1.0)
|
@@ -202,7 +202,7 @@ GEM
|
|
202
202
|
concurrent-ruby (~> 1.0)
|
203
203
|
tzinfo-data (1.2025.2)
|
204
204
|
tzinfo (>= 1.0.0)
|
205
|
-
unicode-display_width (3.1.
|
205
|
+
unicode-display_width (3.1.5)
|
206
206
|
unicode-emoji (~> 4.0, >= 4.0.4)
|
207
207
|
unicode-emoji (4.0.4)
|
208
208
|
uri (1.0.3)
|
data/assets/YouTubeThumb.pxd
CHANGED
Binary file
|
data/bin/new-version
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
set -e
|
2
2
|
|
3
|
+
VIM=nvim
|
3
4
|
if [ -f /.dockerenv ]; then
|
4
|
-
|
5
|
-
exit 1
|
5
|
+
VIM=vim
|
6
6
|
fi
|
7
7
|
|
8
|
-
|
8
|
+
$VIM -o lib/brut/version.rb mkbrut/lib/mkbrut/version.rb brut-js/package.json brut-css/package.json CHANGELOG.md
|
data/brut-css/package-lock.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "brut-css",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.11.0",
|
4
4
|
"lockfileVersion": 3,
|
5
5
|
"requires": true,
|
6
6
|
"packages": {
|
7
7
|
"": {
|
8
8
|
"name": "brut-css",
|
9
|
-
"version": "0.
|
9
|
+
"version": "0.11.0",
|
10
10
|
"license": "Hippocratic-2.1",
|
11
11
|
"devDependencies": {
|
12
12
|
"comment-parser": "^1.4.1",
|
data/brut-css/package.json
CHANGED
data/brut-js/package-lock.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "brut-js",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.11.0",
|
4
4
|
"lockfileVersion": 3,
|
5
5
|
"requires": true,
|
6
6
|
"packages": {
|
7
7
|
"": {
|
8
8
|
"name": "brut-js",
|
9
|
-
"version": "0.
|
9
|
+
"version": "0.11.0",
|
10
10
|
"license": "Hippocratic-2.1",
|
11
11
|
"devDependencies": {
|
12
12
|
"esbuild": "^0.24.0",
|
data/brut-js/package.json
CHANGED
@@ -18,9 +18,12 @@ describe("<brut-cv-messages>", () => {
|
|
18
18
|
|
19
19
|
element.createMessages({validityState,inputName})
|
20
20
|
|
21
|
-
|
21
|
+
const brutCvElements = element.querySelectorAll("brut-cv")
|
22
|
+
assert.equal(brutCvElements.length, 2)
|
22
23
|
assert.match(element.textContent,new RegExp("This field does not match the pattern","m"))
|
23
24
|
assert.match(element.textContent,new RegExp("This field is above the range","m"))
|
25
|
+
assert.equal(brutCvElements[0].getAttribute("client-side"),"")
|
26
|
+
assert.equal(brutCvElements[1].getAttribute("client-side"),"")
|
24
27
|
|
25
28
|
element.clearClientSideMessages()
|
26
29
|
assert.equal(element.textContent,"")
|
data/brut-js/specs/Form.spec.js
CHANGED
@@ -6,12 +6,12 @@ describe("<brut-form>", () => {
|
|
6
6
|
<form>
|
7
7
|
<label>
|
8
8
|
<input required type="text" name="text">
|
9
|
-
<brut-cv-messages>
|
9
|
+
<brut-cv-messages input-name="text">
|
10
10
|
</brut-cv-messages>
|
11
11
|
</label>
|
12
12
|
<label>
|
13
13
|
<input required type="number" name="number">
|
14
|
-
<brut-cv-messages>
|
14
|
+
<brut-cv-messages input-name="number">
|
15
15
|
</brut-cv-messages>
|
16
16
|
</label>
|
17
17
|
<input type="submit">Save</input>
|
@@ -134,48 +134,4 @@ describe("<brut-form>", () => {
|
|
134
134
|
assert(gotValid)
|
135
135
|
assert(!gotInvalid)
|
136
136
|
})
|
137
|
-
withHTML(`
|
138
|
-
<brut-form>
|
139
|
-
<form>
|
140
|
-
<label>
|
141
|
-
<input required type="text" name="text">
|
142
|
-
</label>
|
143
|
-
<brut-cv-messages input-name='text'>
|
144
|
-
</brut-cv-messages>
|
145
|
-
<input type="submit">Save</input>
|
146
|
-
</form>
|
147
|
-
</brut-form>
|
148
|
-
`).test("locates the messages for errors based on name", ({window,document,assert}) => {
|
149
|
-
|
150
|
-
const brutForm = document.querySelector("brut-form")
|
151
|
-
const form = brutForm.querySelector("form")
|
152
|
-
const button = form.querySelector("input[type=submit]")
|
153
|
-
const textFieldLabel = form.querySelector("label:has(input[type=text])")
|
154
|
-
|
155
|
-
let submitted = false
|
156
|
-
let gotInvalid = false
|
157
|
-
let gotValid = false
|
158
|
-
|
159
|
-
form.addEventListener("submit", (event) => {
|
160
|
-
event.preventDefault()
|
161
|
-
submitted = true
|
162
|
-
})
|
163
|
-
brutForm.addEventListener("brut:valid", () => {
|
164
|
-
gotValid = true
|
165
|
-
})
|
166
|
-
brutForm.addEventListener("brut:invalid", () => {
|
167
|
-
gotInvalid = true
|
168
|
-
})
|
169
|
-
|
170
|
-
button.click()
|
171
|
-
|
172
|
-
assert(!submitted)
|
173
|
-
assert(!gotValid)
|
174
|
-
assert(gotInvalid)
|
175
|
-
assert.equal(brutForm.getAttribute("submitted-invalid"),"")
|
176
|
-
|
177
|
-
let error = brutForm.querySelector("brut-cv[input-name='text'][key='cv.cs.valueMissing']")
|
178
|
-
assert(error)
|
179
|
-
|
180
|
-
})
|
181
137
|
})
|
@@ -15,9 +15,15 @@ import I18nTranslation from "./I18nTranslation"
|
|
15
15
|
* @property {string} key - the i18n translation key to use. It must map to the `key` of a `<brut-i18n-translation>` on the page or
|
16
16
|
* the element will not render any text.
|
17
17
|
* @property {string} input-name - the name of the input, used to insert into the message, e.g. "Title is required".
|
18
|
+
* @property {boolean} server-generated if true, this indicates the element's HTML was generated on the server.
|
19
|
+
* This means that your CSS can target it for display in all cases. If this is not present,
|
20
|
+
* you may want to avoid showing this element if the form has not been submitted yet.
|
21
|
+
* Does not affect behavior.
|
18
22
|
* @property {boolean} server-side if true, this indicates the element contains constraint violation messages
|
19
|
-
*
|
20
|
-
*
|
23
|
+
* from the server. Does not affect behavior.
|
24
|
+
* @property {boolean} client-side if true, this indicates the element contains constraint violation messages
|
25
|
+
* from the client, however they may have been generated from the server, since the server may
|
26
|
+
* re-evaluate the client-side constraints. Does not affect behavior of this tag.
|
21
27
|
*
|
22
28
|
* @see I18nTranslation
|
23
29
|
* @see ConstraintViolationMessages
|
@@ -33,12 +39,15 @@ class ConstraintViolationMessage extends BaseCustomElement {
|
|
33
39
|
"key",
|
34
40
|
"input-name",
|
35
41
|
"server-side",
|
42
|
+
"client-side",
|
43
|
+
"server-generated",
|
36
44
|
]
|
37
45
|
|
38
46
|
static createElement(document,attributes) {
|
39
47
|
const element = document.createElement(ConstraintViolationMessage.tagName)
|
40
48
|
element.setAttribute("key",this.i18nKey("cs", attributes.key))
|
41
49
|
element.setAttribute("input-name",attributes["input-name"])
|
50
|
+
element.setAttribute("client-side","")
|
42
51
|
if (Object.hasOwn(attributes,"show-warnings")) {
|
43
52
|
element.setAttribute("show-warnings",attributes["show-warnings"])
|
44
53
|
}
|
@@ -85,6 +94,12 @@ class ConstraintViolationMessage extends BaseCustomElement {
|
|
85
94
|
serverSideChangedCallback({newValueAsBoolean}) {
|
86
95
|
// attribute listed for documentation purposes only
|
87
96
|
}
|
97
|
+
clientSideChangedCallback({newValueAsBoolean}) {
|
98
|
+
// attribute listed for documentation purposes only
|
99
|
+
}
|
100
|
+
serverGeneratedChangedCallback({newValueAsBoolean}) {
|
101
|
+
// attribute listed for documentation purposes only
|
102
|
+
}
|
88
103
|
|
89
104
|
update() {
|
90
105
|
if (!this.#key) {
|
data/brut-js/src/Form.js
CHANGED
@@ -15,10 +15,7 @@ import ConstraintViolationMessages from "./ConstraintViolationMessages"
|
|
15
15
|
* set `submitted-invalid` on itself when that happens, thus allowing you to target invalid
|
16
16
|
* fields only after a submission attempt.
|
17
17
|
* * You may wish to control the messaging of client-side constraint violations
|
18
|
-
* beyond what the browser gives you. Assuming
|
19
|
-
* like `LABEL`, a `brut-cv` tag found in that container
|
20
|
-
* (i.e. a sibling of your `INPUT`) will be modified to contain error messages specific
|
21
|
-
* to the {@link external:ValidityState} of the control.
|
18
|
+
* beyond what the browser gives you. Assuming you have generated a `<brut-cv-messages input-name="«input name»"></brut-cv-messasges>`, it will be populated with `<brut-cv>` elements for each client-side constraint violation, based on the {@link external:ValidityState} of the control.
|
22
19
|
*
|
23
20
|
* @fires brut:invalid Fired when any element is found to be invalid
|
24
21
|
* @fires brut:valid Fired when no element is found to be invalid. This should be reliable to know
|
@@ -29,12 +26,12 @@ import ConstraintViolationMessages from "./ConstraintViolationMessages"
|
|
29
26
|
* <form ...>
|
30
27
|
* <label>
|
31
28
|
* <input type="text" required name="username">
|
32
|
-
* <brut-cv-messages>
|
29
|
+
* <brut-cv-messages input-name="username">
|
33
30
|
* </brut-cv-messages>
|
34
31
|
* </label>
|
35
32
|
* <div> <!-- container need not be a label -->
|
36
33
|
* <input type="text" required minlength="4" name="alias">
|
37
|
-
* <brut-cv-messages>
|
34
|
+
* <brut-cv-messages input-name="alias">
|
38
35
|
* </brut-cv-messages>
|
39
36
|
* </div>
|
40
37
|
* <button>Submit</button>
|
@@ -45,13 +42,13 @@ import ConstraintViolationMessages from "./ConstraintViolationMessages"
|
|
45
42
|
* <form ...>
|
46
43
|
* <label>
|
47
44
|
* <input type="text" required name="username">
|
48
|
-
* <brut-cv-messages>
|
45
|
+
* <brut-cv-messages input-name="username">
|
49
46
|
* <brut-cv>This field is required</brut-cv>
|
50
47
|
* </brut-cv-messages>
|
51
48
|
* </label>
|
52
49
|
* <div> <!-- container need not be a label -->
|
53
50
|
* <input type="text" required minlength="4" name="alias">
|
54
|
-
* <brut-cv-messages>
|
51
|
+
* <brut-cv-messages input-name="alias">
|
55
52
|
* <brut-cv>This field is required</brut-cv>
|
56
53
|
* </brut-cv-messages>
|
57
54
|
* </div>
|
@@ -107,28 +104,27 @@ class Form extends BaseCustomElement {
|
|
107
104
|
|
108
105
|
#updateErrorMessages(event) {
|
109
106
|
const element = event.target
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
107
|
+
let constraintViolationMessages = []
|
108
|
+
if (element.name && element.form) {
|
109
|
+
const selector = `${ConstraintViolationMessages.tagName}[input-name='${element.name}']`
|
110
|
+
constraintViolationMessages = element.form.querySelectorAll(selector)
|
111
|
+
if (constraintViolationMessages.length == 0) {
|
112
|
+
this.logger.warn(`Did not find any elements matching ${selector}, so no error messages will be shown`)
|
113
|
+
}
|
114
|
+
}
|
115
|
+
else {
|
116
|
+
if (element.name) {
|
117
|
+
this.logger.warn("Element has a name (%s), but is not associated with any form.", element.name)
|
119
118
|
}
|
120
119
|
else {
|
121
|
-
this.logger.warn("
|
122
|
-
selector,
|
123
|
-
element.name ? "no name" : "a name, but",
|
124
|
-
element.form ? "no form" : "though has a form")
|
120
|
+
this.logger.warn("Element has a form, but has no name, which means we cannot locate %s by input-name", ConstraintViolationMessages.tagName)
|
125
121
|
}
|
126
122
|
}
|
127
|
-
if (
|
123
|
+
if (constraintViolationMessages.length == 0) {
|
128
124
|
return
|
129
125
|
}
|
130
126
|
let anyErrors = false
|
131
|
-
|
127
|
+
constraintViolationMessages.forEach( (errorLabel) => {
|
132
128
|
if (element.validity.valid) {
|
133
129
|
errorLabel.clearClientSideMessages()
|
134
130
|
}
|
@@ -130,6 +130,7 @@ export default defineConfig({
|
|
130
130
|
collapsed: true,
|
131
131
|
items: [
|
132
132
|
{ text: "Migration Basics", link: "/recipes/migrations" },
|
133
|
+
{ text: "Styling Form Errors", link: "/recipes/form-errors" },
|
133
134
|
{ text: "Authentication", link: "/recipes/authentication" },
|
134
135
|
{ text: "Alternate Layouts", link: "/recipes/alternate-layouts" },
|
135
136
|
{ text: "Blank Layouts", link: "/recipes/blank-layouts" },
|
@@ -120,7 +120,7 @@ inputs `ValidityState`. That may look like so:
|
|
120
120
|
```html {3}
|
121
121
|
<input type="text" name="name" required minlength="3">
|
122
122
|
<brut-cv-messages input-name="name">
|
123
|
-
<brut-cv input-name="name" key="rangeUnderflow"></brut-cv>
|
123
|
+
<brut-cv input-name="name" client-side key="rangeUnderflow"></brut-cv>
|
124
124
|
</brut-cv-messages>
|
125
125
|
```
|
126
126
|
|
@@ -139,7 +139,7 @@ this HTML:
|
|
139
139
|
```html {4}
|
140
140
|
<input type="text" name="name" required minlength="3">
|
141
141
|
<brut-cv-messages input-name="name">
|
142
|
-
<brut-cv input-name="name" key="rangeUnderflow">
|
142
|
+
<brut-cv input-name="name" client-side key="rangeUnderflow">
|
143
143
|
This field is too short
|
144
144
|
</brut-cv>
|
145
145
|
</brut-cv-messages>
|
@@ -154,13 +154,13 @@ violation, the same general markup is generated:
|
|
154
154
|
```html {3,4}
|
155
155
|
<input type="text" name="name" required minlength="3">
|
156
156
|
<brut-cv-messages input-name="name">
|
157
|
-
<brut-cv server-side>
|
157
|
+
<brut-cv server-generated server-side>
|
158
158
|
This name has already been taken.
|
159
159
|
</brut-cv>
|
160
160
|
</brut-cv-messages>
|
161
161
|
```
|
162
162
|
|
163
|
-
The `server-side`
|
163
|
+
The `server-genereted` and `server-side` attributes is set, which can help with CSS targeting.
|
164
164
|
|
165
165
|
The *last* piece of this puzzle is a solution for the issue where forms that have
|
166
166
|
not yet been submitted are considered to have invalid values by the browser.
|
@@ -177,7 +177,7 @@ This might lead to HTML like so:
|
|
177
177
|
|
178
178
|
<input type="text" name="name" required minlength="3">
|
179
179
|
<brut-cv-messages input-name="name">
|
180
|
-
<brut-cv input-name="name" key="rangeUnderflow">
|
180
|
+
<brut-cv input-name="name" client-side key="rangeUnderflow">
|
181
181
|
This field is too short
|
182
182
|
</brut-cv>
|
183
183
|
</brut-cv-messages>
|
@@ -199,7 +199,7 @@ brut-cv {
|
|
199
199
|
/* brut-cv inside a submitted-invalid
|
200
200
|
OR brut-cv from the server ARE shown */
|
201
201
|
brut-form[submitted-invalid] brut-cv,
|
202
|
-
brut-cv[server-
|
202
|
+
brut-cv[server-generated] {
|
203
203
|
display: block;
|
204
204
|
color: red; /* e.g. */
|
205
205
|
}
|
@@ -9,6 +9,7 @@ The simplest way to use `mkbrut` is to use an existing [Docker image](https://hu
|
|
9
9
|
|
10
10
|
```
|
11
11
|
docker run \
|
12
|
+
--pull always \
|
12
13
|
-v "$PWD":"$PWD" \
|
13
14
|
-w "$PWD" \
|
14
15
|
-u $(id -u):$(id -g) \
|
@@ -33,6 +34,7 @@ For now:
|
|
33
34
|
|
34
35
|
``` [Docker-based]
|
35
36
|
docker run \
|
37
|
+
--pull always \
|
36
38
|
-v "$PWD":"$PWD" \
|
37
39
|
-w "$PWD" \
|
38
40
|
-u $(id -u):$(id -g) \
|
@@ -55,6 +57,7 @@ To create your app without the demo components:
|
|
55
57
|
|
56
58
|
``` [Docker-based]
|
57
59
|
docker run \
|
60
|
+
--pull always \
|
58
61
|
-v "$PWD":"$PWD" \
|
59
62
|
-w "$PWD" \
|
60
63
|
-u $(id -u):$(id -g) \
|
Binary file
|
Binary file
|
Binary file
|