brut 0.0.21 → 0.0.23
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/.gitignore +24 -3
- data/.nvim.lua +1 -0
- data/Dockerfile.dx +12 -3
- data/Gemfile.lock +9 -7
- data/README.md +0 -7
- data/Rakefile +6 -4
- data/bin/dev +20 -0
- data/bin/docs +27 -0
- data/bin/setup +47 -1
- data/brut-css/.nvim.lua +1 -0
- data/brut-css/README.md +28 -0
- data/brut-css/bin/build +31 -0
- data/brut-css/bin/dev +1 -0
- data/brut-css/bin/docs +15 -0
- data/brut-css/bin/setup +5 -0
- data/brut-css/config/media-queries-all.css +15 -0
- data/brut-css/config/media-queries-minimal.css +5 -0
- data/brut-css/config/postcss.config.cjs +7 -0
- data/brut-css/config/pseudo-classes-all.css +9 -0
- data/brut-css/dx +1 -0
- data/brut-css/package-lock.json +3217 -0
- data/brut-css/package.json +36 -0
- data/brut-css/src/css/appearance.css +145 -0
- data/brut-css/src/css/border.css +522 -0
- data/brut-css/src/css/colors.css +3502 -0
- data/brut-css/src/css/dimensions.css +548 -0
- data/brut-css/src/css/flex.css +179 -0
- data/brut-css/src/css/index.css +13 -0
- data/brut-css/src/css/layout.css +120 -0
- data/brut-css/src/css/list.css +41 -0
- data/brut-css/src/css/positioning.css +354 -0
- data/brut-css/src/css/properties/colors.css +455 -0
- data/brut-css/src/css/properties/index.css +3 -0
- data/brut-css/src/css/properties/spacing.css +140 -0
- data/brut-css/src/css/properties/typography.css +224 -0
- data/brut-css/src/css/reset.css +107 -0
- data/brut-css/src/css/spacing.css +585 -0
- data/brut-css/src/css/typography.css +519 -0
- data/brut-css/src/css/utils.css +104 -0
- data/brut-css/src/docs/1_getting-started/1_overview.md +46 -0
- data/brut-css/src/docs/1_getting-started/2_installation.md +25 -0
- data/brut-css/src/docs/1_getting-started/3_core-concepts.md +75 -0
- data/brut-css/src/docs/1_getting-started/4_simple-example.md +132 -0
- data/brut-css/src/docs/1_getting-started/page.html.ejs +10 -0
- data/brut-css/src/docs/2_properties/page.html.ejs +71 -0
- data/brut-css/src/docs/3_classes/color-demo.html.ejs +31 -0
- data/brut-css/src/docs/3_classes/page.html.ejs +87 -0
- data/brut-css/src/docs/4_customization/1_design-system.md +36 -0
- data/brut-css/src/docs/4_customization/2_breakpoints.md +75 -0
- data/brut-css/src/docs/4_customization/3_pseudo-classes.md +74 -0
- data/brut-css/src/docs/4_customization/4_advanced-configuration.md +40 -0
- data/brut-css/src/docs/4_customization/page.html.ejs +10 -0
- data/brut-css/src/docs/docs.css +98 -0
- data/brut-css/src/docs/includes/body-and-header.html.ejs +30 -0
- data/brut-css/src/docs/includes/footer-and-rest.html.ejs +9 -0
- data/brut-css/src/docs/includes/head.html.ejs +5 -0
- data/brut-css/src/docs/includes/nav.html.ejs +10 -0
- data/brut-css/src/docs/index.html.ejs +32 -0
- data/brut-css/src/docs/prism-twilight.min.css +1 -0
- data/brut-css/src/js/Logger.js +71 -0
- data/brut-css/src/js/build.js +111 -0
- data/brut-css/src/js/cli/CLIArgError.js +7 -0
- data/brut-css/src/js/cli/Debug.js +27 -0
- data/brut-css/src/js/cli/DocsDir.js +16 -0
- data/brut-css/src/js/cli/DocsTemplateSourceDir.js +16 -0
- data/brut-css/src/js/cli/InputFile.js +31 -0
- data/brut-css/src/js/cli/MediaQueryConfigFile.js +10 -0
- data/brut-css/src/js/cli/OutputFile.js +22 -0
- data/brut-css/src/js/cli/ParsedArg.js +17 -0
- data/brut-css/src/js/cli/PathToBrutCSSRoot.js +19 -0
- data/brut-css/src/js/cli/PseudoClassConfigFile.js +11 -0
- data/brut-css/src/js/cli.js +108 -0
- data/brut-css/src/js/docGenerator.js +467 -0
- data/brut-css/src/js/mediaQueryConfigParser.js +98 -0
- data/brut-css/src/js/post-css-plugins/addMediaQueriesPlugin.js +49 -0
- data/brut-css/src/js/post-css-plugins/addPseudoClassesPlugin.js +42 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/Category.js +9 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/DocState.js +185 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/Documentable.js +8 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/Group.js +7 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/ParsedComment.js +73 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/Property.js +9 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/PropertyCategory.js +4 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/PropertyGroup.js +8 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/Rule.js +12 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/RuleCategory.js +4 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/RuleGroup.js +8 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/SeeRef.js +5 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin/SeeURL.js +9 -0
- data/brut-css/src/js/post-css-plugins/generateDocumentationPlugin.js +49 -0
- data/brut-css/src/js/post-css-plugins/generateRootCustomPropertiesPlugin.js +45 -0
- data/brut-css/src/js/pseudoClassConfigParser.js +145 -0
- data/brut-js/.projections.json +10 -0
- data/brut-js/README.md +118 -0
- data/brut-js/bin/build +10 -0
- data/brut-js/bin/ci +5 -0
- data/brut-js/bin/setup +5 -0
- data/brut-js/docs/README.md +8 -0
- data/brut-js/docs/jsdoc-plugins/customElementTag.js +8 -0
- data/brut-js/docs/jsdoc-theme/publish.js +692 -0
- data/brut-js/docs/jsdoc-theme/static/scripts/linenumber.js +25 -0
- data/brut-js/docs/jsdoc-theme/static/scripts/prettify/Apache-License-2.0.txt +202 -0
- data/brut-js/docs/jsdoc-theme/static/scripts/prettify/lang-css.js +2 -0
- data/brut-js/docs/jsdoc-theme/static/scripts/prettify/prettify.js +28 -0
- data/brut-js/docs/jsdoc-theme/static/styles/jsdoc-default.css +327 -0
- data/brut-js/docs/jsdoc-theme/static/styles/prettify-jsdoc.css +111 -0
- data/brut-js/docs/jsdoc-theme/static/styles/prettify-tomorrow.css +132 -0
- data/brut-js/docs/jsdoc-theme/tmpl/augments.tmpl +10 -0
- data/brut-js/docs/jsdoc-theme/tmpl/container.tmpl +199 -0
- data/brut-js/docs/jsdoc-theme/tmpl/details.tmpl +143 -0
- data/brut-js/docs/jsdoc-theme/tmpl/example.tmpl +2 -0
- data/brut-js/docs/jsdoc-theme/tmpl/examples.tmpl +13 -0
- data/brut-js/docs/jsdoc-theme/tmpl/exceptions.tmpl +32 -0
- data/brut-js/docs/jsdoc-theme/tmpl/layout.tmpl +38 -0
- data/brut-js/docs/jsdoc-theme/tmpl/mainpage.tmpl +14 -0
- data/brut-js/docs/jsdoc-theme/tmpl/members.tmpl +38 -0
- data/brut-js/docs/jsdoc-theme/tmpl/method.tmpl +131 -0
- data/brut-js/docs/jsdoc-theme/tmpl/modifies.tmpl +14 -0
- data/brut-js/docs/jsdoc-theme/tmpl/params.tmpl +131 -0
- data/brut-js/docs/jsdoc-theme/tmpl/properties.tmpl +108 -0
- data/brut-js/docs/jsdoc-theme/tmpl/returns.tmpl +19 -0
- data/brut-js/docs/jsdoc-theme/tmpl/source.tmpl +8 -0
- data/brut-js/docs/jsdoc-theme/tmpl/tutorial.tmpl +19 -0
- data/brut-js/docs/jsdoc-theme/tmpl/type.tmpl +7 -0
- data/brut-js/docs/jsdoc.config.json +23 -0
- data/brut-js/docs/package-lock.json +343 -0
- data/brut-js/docs/package.json +7 -0
- data/brut-js/package-lock.json +2171 -0
- data/brut-js/package.json +32 -0
- data/brut-js/specs/AjaxSubmit.spec.js +256 -0
- data/brut-js/specs/Autosubmit.spec.js +127 -0
- data/brut-js/specs/ConfirmSubmit.spec.js +193 -0
- data/brut-js/specs/ConstraintViolationMessage.spec.js +33 -0
- data/brut-js/specs/ConstraintViolationMessages.spec.js +29 -0
- data/brut-js/specs/CopyToClipboard.spec.js +35 -0
- data/brut-js/specs/Form.spec.js +181 -0
- data/brut-js/specs/I18nTranslation.spec.js +19 -0
- data/brut-js/specs/LocaleDetection.spec.js +22 -0
- data/brut-js/specs/Message.spec.js +15 -0
- data/brut-js/specs/SpecHelper.js +23 -0
- data/brut-js/specs/Tabs.spec.js +41 -0
- data/brut-js/specs/config/asset_metadata.json +7 -0
- data/brut-js/src/AjaxSubmit.js +384 -0
- data/brut-js/src/Autosubmit.js +63 -0
- data/brut-js/src/BaseCustomElement.js +261 -0
- data/brut-js/src/ConfirmSubmit.js +116 -0
- data/brut-js/src/ConfirmationDialog.js +143 -0
- data/brut-js/src/ConstraintViolationMessage.js +125 -0
- data/brut-js/src/ConstraintViolationMessages.js +98 -0
- data/brut-js/src/CopyToClipboard.js +96 -0
- data/brut-js/src/Form.js +151 -0
- data/brut-js/src/I18nTranslation.js +61 -0
- data/brut-js/src/LocaleDetection.js +117 -0
- data/brut-js/src/Logger.js +90 -0
- data/brut-js/src/Message.js +56 -0
- data/brut-js/src/RichString.js +113 -0
- data/brut-js/src/Tabs.js +168 -0
- data/brut-js/src/Tracing.js +247 -0
- data/brut-js/src/appForTestingOnly.js +15 -0
- data/brut-js/src/index.js +130 -0
- data/brut-js/src/testing/AssetMetadata.js +35 -0
- data/brut-js/src/testing/AssetMetadataLoader.js +25 -0
- data/brut-js/src/testing/CustomElementTest.js +235 -0
- data/brut-js/src/testing/DOMCreator.js +45 -0
- data/brut-js/src/testing/index.js +48 -0
- data/brutrb.com/.vitepress/config.mjs +106 -0
- data/brutrb.com/.vitepress/plugins/jsdocLinker.js +34 -0
- data/brutrb.com/.vitepress/plugins/rdocLinker.js +18 -0
- data/brutrb.com/.vitepress/theme/custom.css +7 -0
- data/brutrb.com/.vitepress/theme/index.js +18 -0
- data/brutrb.com/.vitepress/theme/style.css +149 -0
- data/brutrb.com/ai.md +68 -0
- data/brutrb.com/assets.md +138 -0
- data/brutrb.com/bin/build +5 -0
- data/brutrb.com/bin/deploy +7 -0
- data/brutrb.com/bin/dev +5 -0
- data/brutrb.com/bin/setup +5 -0
- data/brutrb.com/brut-js.md +117 -0
- data/brutrb.com/business-logic.md +55 -0
- data/brutrb.com/cli.md +278 -0
- data/brutrb.com/components.md +243 -0
- data/brutrb.com/configuration.md +257 -0
- data/brutrb.com/css.md +103 -0
- data/brutrb.com/custom-element-tests.md +149 -0
- data/brutrb.com/database-access.md +201 -0
- data/brutrb.com/database-schema.md +312 -0
- data/brutrb.com/deployment.md +66 -0
- data/brutrb.com/dev-environment.md +179 -0
- data/brutrb.com/doc-conventions.md +39 -0
- data/brutrb.com/end-to-end-tests.md +174 -0
- data/brutrb.com/flash-and-session.md +224 -0
- data/brutrb.com/forms.md +866 -0
- data/brutrb.com/getting-started.md +66 -0
- data/brutrb.com/handlers.md +153 -0
- data/brutrb.com/hooks.md +178 -0
- data/brutrb.com/i18n.md +188 -0
- data/brutrb.com/images/Makefile +10 -0
- data/brutrb.com/images/dev-env-overview.dot +54 -0
- data/brutrb.com/images/dev-env-overview.png +0 -0
- data/brutrb.com/images/dev-env-protocol.dot +37 -0
- data/brutrb.com/images/dev-env-protocol.png +0 -0
- data/brutrb.com/images/logo-300.png +0 -0
- data/brutrb.com/images/logo.png +0 -0
- data/brutrb.com/images/overview.graffle +0 -0
- data/brutrb.com/images/overview.png +0 -0
- data/brutrb.com/images/spa.dot +19 -0
- data/brutrb.com/images/spa.png +0 -0
- data/brutrb.com/images/workspace-protocol.dot +44 -0
- data/brutrb.com/images/workspace-protocol.png +0 -0
- data/brutrb.com/index.md +36 -0
- data/brutrb.com/instrumentation.md +183 -0
- data/brutrb.com/javascript.md +122 -0
- data/brutrb.com/jobs.md +14 -0
- data/brutrb.com/keyword-injection.md +237 -0
- data/brutrb.com/markdown-examples.md +85 -0
- data/brutrb.com/middleware.md +80 -0
- data/brutrb.com/not-released.md +5 -0
- data/brutrb.com/overview.md +404 -0
- data/brutrb.com/package-lock.json +2404 -0
- data/brutrb.com/package.json +11 -0
- data/brutrb.com/pages.md +378 -0
- data/brutrb.com/public/images/logo-300.png +0 -0
- data/brutrb.com/public/images/logo.png +0 -0
- data/brutrb.com/routes.md +215 -0
- data/brutrb.com/security.md +105 -0
- data/brutrb.com/seed-data.md +63 -0
- data/brutrb.com/space-time-continuum.md +85 -0
- data/brutrb.com/tutorial.md +3 -0
- data/brutrb.com/unit-tests.md +148 -0
- data/docker-compose.dx.yml +6 -3
- data/docs/404.html +21 -0
- data/docs/CNAME +1 -0
- data/docs/ai.html +24 -0
- data/docs/api/Brut/BackEnd/SeedData.html +493 -0
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server/FlushSpans.html +214 -0
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares/Server.html +125 -0
- data/docs/api/Brut/BackEnd/Sidekiq/Middlewares.html +125 -0
- data/docs/api/Brut/BackEnd/Sidekiq.html +125 -0
- data/docs/api/Brut/BackEnd/Validators/FormValidator.html +414 -0
- data/docs/api/Brut/BackEnd/Validators.html +128 -0
- data/docs/api/Brut/BackEnd.html +132 -0
- data/docs/api/Brut/CLI/App.html +1576 -0
- data/docs/api/Brut/CLI/AppRunner.html +491 -0
- data/docs/api/Brut/CLI/Apps/BuildAssets/All.html +264 -0
- data/docs/api/Brut/CLI/Apps/BuildAssets/CSS.html +306 -0
- data/docs/api/Brut/CLI/Apps/BuildAssets/Images.html +262 -0
- data/docs/api/Brut/CLI/Apps/BuildAssets/JS.html +314 -0
- data/docs/api/Brut/CLI/Apps/BuildAssets.html +183 -0
- data/docs/api/Brut/CLI/Apps/DB/Create.html +365 -0
- data/docs/api/Brut/CLI/Apps/DB/Drop.html +357 -0
- data/docs/api/Brut/CLI/Apps/DB/Migrate.html +383 -0
- data/docs/api/Brut/CLI/Apps/DB/NewMigration.html +335 -0
- data/docs/api/Brut/CLI/Apps/DB/Rebuild.html +329 -0
- data/docs/api/Brut/CLI/Apps/DB/Seed.html +347 -0
- data/docs/api/Brut/CLI/Apps/DB/Status.html +383 -0
- data/docs/api/Brut/CLI/Apps/DB.html +183 -0
- data/docs/api/Brut/CLI/Apps/Scaffold/Action/Route.html +303 -0
- data/docs/api/Brut/CLI/Apps/Scaffold/Action.html +512 -0
- data/docs/api/Brut/CLI/Apps/Scaffold/Component.html +398 -0
- data/docs/api/Brut/CLI/Apps/Scaffold/CustomElementTest.html +374 -0
- data/docs/api/Brut/CLI/Apps/Scaffold/E2ETest.html +410 -0
- data/docs/api/Brut/CLI/Apps/Scaffold/Form.html +262 -0
- data/docs/api/Brut/CLI/Apps/Scaffold/Page/Route.html +303 -0
- data/docs/api/Brut/CLI/Apps/Scaffold/Page.html +480 -0
- data/docs/api/Brut/CLI/Apps/Scaffold/RoutesEditor.html +450 -0
- data/docs/api/Brut/CLI/Apps/Scaffold/Test.html +380 -0
- data/docs/api/Brut/CLI/Apps/Scaffold.html +253 -0
- data/docs/api/Brut/CLI/Apps/Test/Audit.html +464 -0
- data/docs/api/Brut/CLI/Apps/Test/E2e.html +407 -0
- data/docs/api/Brut/CLI/Apps/Test/JS.html +262 -0
- data/docs/api/Brut/CLI/Apps/Test/Run.html +578 -0
- data/docs/api/Brut/CLI/Apps/Test.html +253 -0
- data/docs/api/Brut/CLI/Apps.html +125 -0
- data/docs/api/Brut/CLI/Command.html +2342 -0
- data/docs/api/Brut/CLI/Error.html +139 -0
- data/docs/api/Brut/CLI/ExecutionResults/Result.html +664 -0
- data/docs/api/Brut/CLI/ExecutionResults.html +675 -0
- data/docs/api/Brut/CLI/Executor.html +430 -0
- data/docs/api/Brut/CLI/InvalidOption.html +245 -0
- data/docs/api/Brut/CLI/Options.html +753 -0
- data/docs/api/Brut/CLI/Output.html +699 -0
- data/docs/api/Brut/CLI/SystemExecError.html +451 -0
- data/docs/api/Brut/CLI.html +263 -0
- data/docs/api/Brut/FactoryBot.html +225 -0
- data/docs/api/Brut/Framework/App.html +1097 -0
- data/docs/api/Brut/Framework/Config.html +1045 -0
- data/docs/api/Brut/Framework/Container.html +1379 -0
- data/docs/api/Brut/Framework/Error.html +140 -0
- data/docs/api/Brut/Framework/Errors/AbstractMethod.html +144 -0
- data/docs/api/Brut/Framework/Errors/Bug.html +234 -0
- data/docs/api/Brut/Framework/Errors/MissingConfiguration.html +257 -0
- data/docs/api/Brut/Framework/Errors/MissingParameter.html +273 -0
- data/docs/api/Brut/Framework/Errors/NoClassForPath.html +471 -0
- data/docs/api/Brut/Framework/Errors/NotFound.html +308 -0
- data/docs/api/Brut/Framework/Errors/NotImplemented.html +234 -0
- data/docs/api/Brut/Framework/Errors.html +328 -0
- data/docs/api/Brut/Framework/FussyTypeEnforcement.html +392 -0
- data/docs/api/Brut/Framework/MCP.html +861 -0
- data/docs/api/Brut/Framework/ProjectEnvironment.html +648 -0
- data/docs/api/Brut/Framework.html +129 -0
- data/docs/api/Brut/FrontEnd/AssetPathResolver.html +317 -0
- data/docs/api/Brut/FrontEnd/Component/Helpers.html +326 -0
- data/docs/api/Brut/FrontEnd/Component.html +365 -0
- data/docs/api/Brut/FrontEnd/Components/ConstraintViolations.html +470 -0
- data/docs/api/Brut/FrontEnd/Components/FormTag.html +518 -0
- data/docs/api/Brut/FrontEnd/Components/I18nTranslations.html +317 -0
- data/docs/api/Brut/FrontEnd/Components/Input.html +195 -0
- data/docs/api/Brut/FrontEnd/Components/Inputs/CsrfToken.html +339 -0
- data/docs/api/Brut/FrontEnd/Components/Inputs/InputTag.html +660 -0
- data/docs/api/Brut/FrontEnd/Components/Inputs/RadioButton.html +417 -0
- data/docs/api/Brut/FrontEnd/Components/Inputs/SelectTagWithOptions.html +918 -0
- data/docs/api/Brut/FrontEnd/Components/Inputs/TextareaTag.html +651 -0
- data/docs/api/Brut/FrontEnd/Components/Inputs.html +125 -0
- data/docs/api/Brut/FrontEnd/Components/LocaleDetection.html +367 -0
- data/docs/api/Brut/FrontEnd/Components/PageIdentifier.html +336 -0
- data/docs/api/Brut/FrontEnd/Components/TimeTag.html +655 -0
- data/docs/api/Brut/FrontEnd/Components/Traceparent.html +352 -0
- data/docs/api/Brut/FrontEnd/Components.html +135 -0
- data/docs/api/Brut/FrontEnd/Download.html +467 -0
- data/docs/api/Brut/FrontEnd/Flash.html +1150 -0
- data/docs/api/Brut/FrontEnd/Form.html +1157 -0
- data/docs/api/Brut/FrontEnd/Forms/ConstraintViolation.html +634 -0
- data/docs/api/Brut/FrontEnd/Forms/Input.html +615 -0
- data/docs/api/Brut/FrontEnd/Forms/InputDeclarations.html +547 -0
- data/docs/api/Brut/FrontEnd/Forms/InputDefinition.html +1318 -0
- data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInput.html +609 -0
- data/docs/api/Brut/FrontEnd/Forms/RadioButtonGroupInputDefinition.html +587 -0
- data/docs/api/Brut/FrontEnd/Forms/SelectInput.html +613 -0
- data/docs/api/Brut/FrontEnd/Forms/SelectInputDefinition.html +582 -0
- data/docs/api/Brut/FrontEnd/Forms/ValidityState.html +609 -0
- data/docs/api/Brut/FrontEnd/Forms.html +127 -0
- data/docs/api/Brut/FrontEnd/GenericResponse.html +377 -0
- data/docs/api/Brut/FrontEnd/Handler.html +442 -0
- data/docs/api/Brut/FrontEnd/Handlers/CspReportingHandler.html +318 -0
- data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler/TraceParent.html +336 -0
- data/docs/api/Brut/FrontEnd/Handlers/InstrumentationHandler.html +399 -0
- data/docs/api/Brut/FrontEnd/Handlers/LocaleDetectionHandler.html +354 -0
- data/docs/api/Brut/FrontEnd/Handlers/MissingHandler/Form.html +151 -0
- data/docs/api/Brut/FrontEnd/Handlers/MissingHandler.html +315 -0
- data/docs/api/Brut/FrontEnd/Handlers.html +125 -0
- data/docs/api/Brut/FrontEnd/HandlingResults.html +339 -0
- data/docs/api/Brut/FrontEnd/HttpMethod.html +661 -0
- data/docs/api/Brut/FrontEnd/HttpStatus.html +496 -0
- data/docs/api/Brut/FrontEnd/InlineSvgLocator.html +284 -0
- data/docs/api/Brut/FrontEnd/Layout.html +318 -0
- data/docs/api/Brut/FrontEnd/Middleware.html +135 -0
- data/docs/api/Brut/FrontEnd/Middlewares/AnnotateBrutOwnedPaths.html +288 -0
- data/docs/api/Brut/FrontEnd/Middlewares/Favicon.html +292 -0
- data/docs/api/Brut/FrontEnd/Middlewares/OpenTelemetrySpan.html +324 -0
- data/docs/api/Brut/FrontEnd/Middlewares/ReloadApp.html +372 -0
- data/docs/api/Brut/FrontEnd/Middlewares.html +125 -0
- data/docs/api/Brut/FrontEnd/Page.html +773 -0
- data/docs/api/Brut/FrontEnd/Pages/MissingPage.html +797 -0
- data/docs/api/Brut/FrontEnd/Pages.html +125 -0
- data/docs/api/Brut/FrontEnd/RequestContext.html +1312 -0
- data/docs/api/Brut/FrontEnd/RouteHook.html +424 -0
- data/docs/api/Brut/FrontEnd/RouteHooks/AgeFlash.html +242 -0
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineScripts.html +249 -0
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts/ReportOnly.html +264 -0
- data/docs/api/Brut/FrontEnd/RouteHooks/CSPNoInlineStylesOrScripts.html +261 -0
- data/docs/api/Brut/FrontEnd/RouteHooks/LocaleDetection.html +284 -0
- data/docs/api/Brut/FrontEnd/RouteHooks/SetupRequestContext.html +252 -0
- data/docs/api/Brut/FrontEnd/RouteHooks.html +115 -0
- data/docs/api/Brut/FrontEnd/Routing/FormHandlerRoute.html +227 -0
- data/docs/api/Brut/FrontEnd/Routing/FormRoute.html +305 -0
- data/docs/api/Brut/FrontEnd/Routing/MissingForm.html +324 -0
- data/docs/api/Brut/FrontEnd/Routing/MissingHandler.html +319 -0
- data/docs/api/Brut/FrontEnd/Routing/MissingPage.html +315 -0
- data/docs/api/Brut/FrontEnd/Routing/MissingPath.html +315 -0
- data/docs/api/Brut/FrontEnd/Routing/PageRoute.html +327 -0
- data/docs/api/Brut/FrontEnd/Routing/Route.html +761 -0
- data/docs/api/Brut/FrontEnd/Routing.html +927 -0
- data/docs/api/Brut/FrontEnd/Session.html +1195 -0
- data/docs/api/Brut/FrontEnd.html +134 -0
- data/docs/api/Brut/I18n/BaseMethods.html +931 -0
- data/docs/api/Brut/I18n/ForBackEnd.html +302 -0
- data/docs/api/Brut/I18n/ForCLI.html +302 -0
- data/docs/api/Brut/I18n/ForHTML.html +296 -0
- data/docs/api/Brut/I18n/HTTPAcceptLanguage/AlwaysEnglish.html +316 -0
- data/docs/api/Brut/I18n/HTTPAcceptLanguage.html +930 -0
- data/docs/api/Brut/I18n.html +127 -0
- data/docs/api/Brut/Instrumentation/LoggerSpanExporter.html +435 -0
- data/docs/api/Brut/Instrumentation/OpenTelemetry/NormalizedAttributes.html +286 -0
- data/docs/api/Brut/Instrumentation/OpenTelemetry/Span.html +302 -0
- data/docs/api/Brut/Instrumentation/OpenTelemetry.html +864 -0
- data/docs/api/Brut/Instrumentation.html +126 -0
- data/docs/api/Brut/SinatraHelpers/ClassMethods.html +532 -0
- data/docs/api/Brut/SinatraHelpers.html +281 -0
- data/docs/api/Brut/SpecSupport/ClockSupport.html +383 -0
- data/docs/api/Brut/SpecSupport/ComponentSupport.html +502 -0
- data/docs/api/Brut/SpecSupport/E2ETestServer.html +503 -0
- data/docs/api/Brut/SpecSupport/E2eSupport.html +142 -0
- data/docs/api/Brut/SpecSupport/EnhancedNode.html +403 -0
- data/docs/api/Brut/SpecSupport/FlashSupport.html +278 -0
- data/docs/api/Brut/SpecSupport/GeneralSupport/ClassMethods.html +401 -0
- data/docs/api/Brut/SpecSupport/GeneralSupport.html +195 -0
- data/docs/api/Brut/SpecSupport/HandlerSupport.html +160 -0
- data/docs/api/Brut/SpecSupport/Matchers/HaveConstraintViolation.html +553 -0
- data/docs/api/Brut/SpecSupport/Matchers/HaveHTMLAttribute.html +439 -0
- data/docs/api/Brut/SpecSupport/Matchers.html +125 -0
- data/docs/api/Brut/SpecSupport/RSpecSetup/OptionalSidekiqSupport.html +335 -0
- data/docs/api/Brut/SpecSupport/RSpecSetup.html +602 -0
- data/docs/api/Brut/SpecSupport/SessionSupport.html +196 -0
- data/docs/api/Brut/SpecSupport.html +129 -0
- data/docs/api/Brut.html +225 -0
- data/docs/api/Clock.html +603 -0
- data/docs/api/RichString.html +968 -0
- data/docs/api/SemanticLogger/Appender/Async.html +219 -0
- data/docs/api/Sequel/Extensions/BrutInstrumentation.html +115 -0
- data/docs/api/Sequel/Extensions/BrutMigrations.html +533 -0
- data/docs/api/Sequel/Extensions.html +117 -0
- data/docs/api/Sequel/Plugins/CreatedAt/InstanceMethods.html +105 -0
- data/docs/api/Sequel/Plugins/CreatedAt.html +125 -0
- data/docs/api/Sequel/Plugins/ExternalId/ClassMethods.html +207 -0
- data/docs/api/Sequel/Plugins/ExternalId/InstanceMethods.html +186 -0
- data/docs/api/Sequel/Plugins/ExternalId.html +218 -0
- data/docs/api/Sequel/Plugins/FindBang/ClassMethods.html +202 -0
- data/docs/api/Sequel/Plugins/FindBang.html +125 -0
- data/docs/api/Sequel/Plugins.html +117 -0
- data/docs/api/Sequel.html +117 -0
- data/docs/api/_index.html +1553 -0
- data/docs/api/class_list.html +54 -0
- data/docs/api/css/common.css +1 -0
- data/docs/api/css/full_list.css +58 -0
- data/docs/api/css/style.css +503 -0
- data/docs/api/file.README.html +127 -0
- data/docs/api/file_list.html +59 -0
- data/docs/api/frames.html +22 -0
- data/docs/api/index.html +127 -0
- data/docs/api/js/app.js +344 -0
- data/docs/api/js/full_list.js +242 -0
- data/docs/api/js/jquery.js +4 -0
- data/docs/api/method_list.html +3998 -0
- data/docs/api/top-level-namespace.html +112 -0
- data/docs/assets/ai.md.tZrjP9im.js +1 -0
- data/docs/assets/ai.md.tZrjP9im.lean.js +1 -0
- data/docs/assets/app.D_yaTITQ.js +1 -0
- data/docs/assets/assets.md.D3wunzLx.js +19 -0
- data/docs/assets/assets.md.D3wunzLx.lean.js +1 -0
- data/docs/assets/brut-js.md.o2DAO2s2.js +12 -0
- data/docs/assets/brut-js.md.o2DAO2s2.lean.js +1 -0
- data/docs/assets/business-logic.md.BY4hGy0m.js +1 -0
- data/docs/assets/business-logic.md.BY4hGy0m.lean.js +1 -0
- data/docs/assets/chunks/@localSearchIndexroot.BsN5i0Fi.js +1 -0
- data/docs/assets/chunks/VPLocalSearchBox.B2-ZzyTY.js +8 -0
- data/docs/assets/chunks/framework.1L-BeKqY.js +18 -0
- data/docs/assets/chunks/theme.CfGFVRvE.js +2 -0
- data/docs/assets/cli.md.RmeA2b0i.js +127 -0
- data/docs/assets/cli.md.RmeA2b0i.lean.js +1 -0
- data/docs/assets/components.md.eCttGlN-.js +104 -0
- data/docs/assets/components.md.eCttGlN-.lean.js +1 -0
- data/docs/assets/configuration.md.BRriU0cL.js +78 -0
- data/docs/assets/configuration.md.BRriU0cL.lean.js +1 -0
- data/docs/assets/css.md.DJgj2clw.js +21 -0
- data/docs/assets/css.md.DJgj2clw.lean.js +1 -0
- data/docs/assets/custom-element-tests.md.BrYJQEl3.js +69 -0
- data/docs/assets/custom-element-tests.md.BrYJQEl3.lean.js +1 -0
- data/docs/assets/database-access.md.C7l-Vuvb.js +63 -0
- data/docs/assets/database-access.md.C7l-Vuvb.lean.js +1 -0
- data/docs/assets/database-schema.md.BUjR0VS1.js +63 -0
- data/docs/assets/database-schema.md.BUjR0VS1.lean.js +1 -0
- data/docs/assets/deployment.md.Dbka4OTr.js +1 -0
- data/docs/assets/deployment.md.Dbka4OTr.lean.js +1 -0
- data/docs/assets/dev-env-overview.Gj7NWM8-.png +0 -0
- data/docs/assets/dev-env-protocol.DysDAtnz.png +0 -0
- data/docs/assets/dev-environment.md.BNc8AYiK.js +11 -0
- data/docs/assets/dev-environment.md.BNc8AYiK.lean.js +1 -0
- data/docs/assets/doc-conventions.md.DCfRXXi-.js +1 -0
- data/docs/assets/doc-conventions.md.DCfRXXi-.lean.js +1 -0
- data/docs/assets/end-to-end-tests.md.yfQHC0b5.js +26 -0
- data/docs/assets/end-to-end-tests.md.yfQHC0b5.lean.js +1 -0
- data/docs/assets/flash-and-session.md.BXY8RvT0.js +93 -0
- data/docs/assets/flash-and-session.md.BXY8RvT0.lean.js +1 -0
- data/docs/assets/forms.md.CBTYQ_Cz.js +379 -0
- data/docs/assets/forms.md.CBTYQ_Cz.lean.js +1 -0
- data/docs/assets/getting-started.md.Bz2s1Vjb.js +2 -0
- data/docs/assets/getting-started.md.Bz2s1Vjb.lean.js +1 -0
- data/docs/assets/handlers.md.089DVD3v.js +69 -0
- data/docs/assets/handlers.md.089DVD3v.lean.js +1 -0
- data/docs/assets/hooks.md.C4-moMny.js +80 -0
- data/docs/assets/hooks.md.C4-moMny.lean.js +1 -0
- data/docs/assets/i18n.md.Do9i1qWl.js +23 -0
- data/docs/assets/i18n.md.Do9i1qWl.lean.js +1 -0
- data/docs/assets/index.md.B28EwVpq.js +1 -0
- data/docs/assets/index.md.B28EwVpq.lean.js +1 -0
- data/docs/assets/instrumentation.md.CL6ax7nT.js +35 -0
- data/docs/assets/instrumentation.md.CL6ax7nT.lean.js +1 -0
- data/docs/assets/javascript.md.GWbhRS51.js +31 -0
- data/docs/assets/javascript.md.GWbhRS51.lean.js +1 -0
- data/docs/assets/jobs.md.S-2amAYp.js +1 -0
- data/docs/assets/jobs.md.S-2amAYp.lean.js +1 -0
- data/docs/assets/keyword-injection.md.Dt2tKREs.js +25 -0
- data/docs/assets/keyword-injection.md.Dt2tKREs.lean.js +1 -0
- data/docs/assets/markdown-examples.md.CCFEQO44.js +33 -0
- data/docs/assets/markdown-examples.md.CCFEQO44.lean.js +1 -0
- data/docs/assets/middleware.md.Czz_UlJN.js +20 -0
- data/docs/assets/middleware.md.Czz_UlJN.lean.js +1 -0
- data/docs/assets/not-released.md.BBy28McC.js +1 -0
- data/docs/assets/not-released.md.BBy28McC.lean.js +1 -0
- data/docs/assets/overview.Da81cB9R.png +0 -0
- data/docs/assets/overview.md.CDalkuxV.js +133 -0
- data/docs/assets/overview.md.CDalkuxV.lean.js +1 -0
- data/docs/assets/pages.md.BE3kfOc5.js +122 -0
- data/docs/assets/pages.md.BE3kfOc5.lean.js +1 -0
- data/docs/assets/routes.md.BMM7peut.js +29 -0
- data/docs/assets/routes.md.BMM7peut.lean.js +1 -0
- data/docs/assets/security.md.C668yXCi.js +1 -0
- data/docs/assets/security.md.C668yXCi.lean.js +1 -0
- data/docs/assets/seed-data.md.BvFZlqIk.js +14 -0
- data/docs/assets/seed-data.md.BvFZlqIk.lean.js +1 -0
- data/docs/assets/spa.qejUdp-5.png +0 -0
- data/docs/assets/space-time-continuum.md.KPUIKysQ.js +1 -0
- data/docs/assets/space-time-continuum.md.KPUIKysQ.lean.js +1 -0
- data/docs/assets/style.D73IYGCX.css +1 -0
- data/docs/assets/tutorial.md.BnoGjrdK.js +1 -0
- data/docs/assets/tutorial.md.BnoGjrdK.lean.js +1 -0
- data/docs/assets/unit-tests.md.DUGrnLj5.js +13 -0
- data/docs/assets/unit-tests.md.DUGrnLj5.lean.js +1 -0
- data/docs/assets/workspace-protocol.C0gXsoDb.png +0 -0
- data/docs/assets.html +42 -0
- data/docs/brut-css/brut.css +1 -0
- data/docs/brut-css/brut.max.css +22372 -0
- data/docs/brut-css/classes/appearances.html +783 -0
- data/docs/brut-css/classes/background-colors.html +3529 -0
- data/docs/brut-css/classes/border-colors.html +3529 -0
- data/docs/brut-css/classes/borders.html +2293 -0
- data/docs/brut-css/classes/dimensions.html +2581 -0
- data/docs/brut-css/classes/flex.html +917 -0
- data/docs/brut-css/classes/foreground-colors.html +3261 -0
- data/docs/brut-css/classes/junk-drawer.html +431 -0
- data/docs/brut-css/classes/layout.html +668 -0
- data/docs/brut-css/classes/lists.html +331 -0
- data/docs/brut-css/classes/positioning.html +1751 -0
- data/docs/brut-css/classes/spacings.html +2633 -0
- data/docs/brut-css/classes/typography.html +2206 -0
- data/docs/brut-css/customization/advanced-configuration.html +204 -0
- data/docs/brut-css/customization/breakpoints.html +227 -0
- data/docs/brut-css/customization/design-system.html +197 -0
- data/docs/brut-css/customization/pseudo-classes.html +228 -0
- data/docs/brut-css/docs.css +98 -0
- data/docs/brut-css/getting-started/core-concepts.html +234 -0
- data/docs/brut-css/getting-started/installation.html +190 -0
- data/docs/brut-css/getting-started/overview.html +210 -0
- data/docs/brut-css/getting-started/simple-example.html +285 -0
- data/docs/brut-css/index.html +193 -0
- data/docs/brut-css/prism-twilight.min.css +1 -0
- data/docs/brut-css/properties/colors.html +1548 -0
- data/docs/brut-css/properties/spacings.html +614 -0
- data/docs/brut-css/properties/typography.html +777 -0
- data/docs/brut-js/api/AjaxSubmit.html +374 -0
- data/docs/brut-js/api/AjaxSubmit.js.html +435 -0
- data/docs/brut-js/api/Autosubmit.html +192 -0
- data/docs/brut-js/api/Autosubmit.js.html +114 -0
- data/docs/brut-js/api/BaseCustomElement.html +1091 -0
- data/docs/brut-js/api/BaseCustomElement.js.html +312 -0
- data/docs/brut-js/api/BrutCustomElements.html +172 -0
- data/docs/brut-js/api/BufferedLogger.html +173 -0
- data/docs/brut-js/api/ConfirmSubmit.html +278 -0
- data/docs/brut-js/api/ConfirmSubmit.js.html +167 -0
- data/docs/brut-js/api/ConfirmationDialog.html +425 -0
- data/docs/brut-js/api/ConfirmationDialog.js.html +194 -0
- data/docs/brut-js/api/ConstraintViolationMessage.html +448 -0
- data/docs/brut-js/api/ConstraintViolationMessage.js.html +176 -0
- data/docs/brut-js/api/ConstraintViolationMessages.html +590 -0
- data/docs/brut-js/api/ConstraintViolationMessages.js.html +149 -0
- data/docs/brut-js/api/CopyToClipboard.html +345 -0
- data/docs/brut-js/api/CopyToClipboard.js.html +147 -0
- data/docs/brut-js/api/Form.html +294 -0
- data/docs/brut-js/api/Form.js.html +202 -0
- data/docs/brut-js/api/I18nTranslation.html +409 -0
- data/docs/brut-js/api/I18nTranslation.js.html +112 -0
- data/docs/brut-js/api/LocaleDetection.html +312 -0
- data/docs/brut-js/api/LocaleDetection.js.html +168 -0
- data/docs/brut-js/api/Logger.html +702 -0
- data/docs/brut-js/api/Logger.js.html +141 -0
- data/docs/brut-js/api/Message.html +238 -0
- data/docs/brut-js/api/Message.js.html +107 -0
- data/docs/brut-js/api/PrefixedLogger.html +369 -0
- data/docs/brut-js/api/RichString.html +1049 -0
- data/docs/brut-js/api/RichString.js.html +164 -0
- data/docs/brut-js/api/Tabs.html +295 -0
- data/docs/brut-js/api/Tabs.js.html +219 -0
- data/docs/brut-js/api/Tracing.html +277 -0
- data/docs/brut-js/api/Tracing.js.html +298 -0
- data/docs/brut-js/api/external-CustomElementRegistry.html +140 -0
- data/docs/brut-js/api/external-Performance.html +138 -0
- data/docs/brut-js/api/external-Promise.html +138 -0
- data/docs/brut-js/api/external-ValidityState.html +138 -0
- data/docs/brut-js/api/external-Window.html +233 -0
- data/docs/brut-js/api/external-fetch.html +138 -0
- data/docs/brut-js/api/global.html +400 -0
- data/docs/brut-js/api/index.html +168 -0
- data/docs/brut-js/api/index.js.html +181 -0
- data/docs/brut-js/api/module-testing.html +383 -0
- data/docs/brut-js/api/scripts/linenumber.js +25 -0
- data/docs/brut-js/api/scripts/prettify/Apache-License-2.0.txt +202 -0
- data/docs/brut-js/api/scripts/prettify/lang-css.js +2 -0
- data/docs/brut-js/api/scripts/prettify/prettify.js +28 -0
- data/docs/brut-js/api/styles/jsdoc-default.css +327 -0
- data/docs/brut-js/api/styles/prettify-jsdoc.css +111 -0
- data/docs/brut-js/api/styles/prettify-tomorrow.css +132 -0
- data/docs/brut-js/api/testing.AssetMetadata.html +172 -0
- data/docs/brut-js/api/testing.AssetMetadataLoader.html +171 -0
- data/docs/brut-js/api/testing.CustomElementTest.html +679 -0
- data/docs/brut-js/api/testing.DOMCreator.html +171 -0
- data/docs/brut-js/api/testing_AssetMetadata.js.html +86 -0
- data/docs/brut-js/api/testing_AssetMetadataLoader.js.html +76 -0
- data/docs/brut-js/api/testing_CustomElementTest.js.html +286 -0
- data/docs/brut-js/api/testing_DOMCreator.js.html +96 -0
- data/docs/brut-js/api/testing_index.js.html +99 -0
- data/docs/brut-js.html +35 -0
- data/docs/business-logic.html +24 -0
- data/docs/cli.html +150 -0
- data/docs/components.html +127 -0
- data/docs/configuration.html +101 -0
- data/docs/css.html +44 -0
- data/docs/custom-element-tests.html +92 -0
- data/docs/database-access.html +86 -0
- data/docs/database-schema.html +86 -0
- data/docs/deployment.html +24 -0
- data/docs/dev-environment.html +34 -0
- data/docs/doc-conventions.html +24 -0
- data/docs/end-to-end-tests.html +49 -0
- data/docs/flash-and-session.html +116 -0
- data/docs/forms.html +402 -0
- data/docs/getting-started.html +25 -0
- data/docs/handlers.html +92 -0
- data/docs/hashmap.json +1 -0
- data/docs/hooks.html +103 -0
- data/docs/i18n.html +46 -0
- data/docs/images/logo-300.png +0 -0
- data/docs/images/logo.png +0 -0
- data/docs/index.html +24 -0
- data/docs/instrumentation.html +58 -0
- data/docs/javascript.html +54 -0
- data/docs/jobs.html +24 -0
- data/docs/keyword-injection.html +48 -0
- data/docs/markdown-examples.html +56 -0
- data/docs/middleware.html +43 -0
- data/docs/not-released.html +24 -0
- data/docs/overview.html +156 -0
- data/docs/pages.html +145 -0
- data/docs/routes.html +52 -0
- data/docs/security.html +24 -0
- data/docs/seed-data.html +37 -0
- data/docs/space-time-continuum.html +24 -0
- data/docs/tutorial.html +24 -0
- data/docs/unit-tests.html +36 -0
- data/docs/vp-icons.css +1 -0
- data/lib/brut/cli/app_runner.rb +1 -1
- data/lib/brut/cli/apps/test.rb +5 -0
- data/lib/brut/framework/mcp.rb +0 -4
- data/lib/brut/front_end/component.rb +59 -84
- data/lib/brut/front_end/components/constraint_violations.rb +1 -4
- data/lib/brut/front_end/components/form_tag.rb +1 -1
- data/lib/brut/front_end/components/input.rb +3 -3
- data/lib/brut/front_end/components/inputs/csrf_token.rb +1 -1
- data/lib/brut/front_end/components/inputs/{text_field.rb → input_tag.rb} +6 -8
- data/lib/brut/front_end/components/inputs/radio_button.rb +1 -1
- data/lib/brut/front_end/components/inputs/select_tag_with_options.rb +187 -0
- data/lib/brut/front_end/components/inputs/{textarea.rb → textarea_tag.rb} +2 -2
- data/lib/brut/front_end/components/time_tag.rb +2 -1
- data/lib/brut/front_end/form.rb +4 -4
- data/lib/brut/front_end/forms/input.rb +2 -1
- data/lib/brut/front_end/forms/input_definition.rb +5 -2
- data/lib/brut/front_end/forms/radio_button_group_input.rb +2 -1
- data/lib/brut/front_end/forms/radio_button_group_input_definition.rb +2 -2
- data/lib/brut/front_end/forms/select_input.rb +2 -4
- data/lib/brut/front_end/forms/select_input_definition.rb +2 -2
- data/lib/brut/front_end/handler.rb +28 -26
- data/lib/brut/front_end/handlers/csp_reporting_handler.rb +5 -2
- data/lib/brut/front_end/handlers/instrumentation_handler.rb +8 -4
- data/lib/brut/front_end/handlers/locale_detection_handler.rb +9 -5
- data/lib/brut/front_end/handlers/missing_handler.rb +5 -2
- data/lib/brut/front_end/page.rb +4 -6
- data/lib/brut/front_end/request_context.rb +3 -2
- data/lib/brut/i18n/base_methods.rb +136 -82
- data/lib/brut/i18n/for_back_end.rb +1 -0
- data/lib/brut/i18n/for_cli.rb +1 -0
- data/lib/brut/i18n/for_html.rb +32 -4
- data/lib/brut/instrumentation/open_telemetry.rb +12 -2
- data/lib/brut/sinatra_helpers.rb +10 -3
- data/lib/brut/spec_support/component_support.rb +18 -18
- data/lib/brut/spec_support/e2e_test_server.rb +3 -0
- data/lib/brut/version.rb +1 -1
- data/lib/sequel/extensions/brut_migrations.rb +12 -9
- metadata +647 -5
- data/lib/brut/front_end/components/inputs/select.rb +0 -117
@@ -1,9 +1,12 @@
|
|
1
1
|
# Receives content security policy violations and logs them. This is set up in {Brut::Framework::MCP}, however CSP reporting is
|
2
2
|
# configured in {Brut::FrontEnd::RouteHooks::CSPNoInlineStylesOrScripts::ReportOnly}.
|
3
3
|
class Brut::FrontEnd::Handlers::CspReportingHandler < Brut::FrontEnd::Handler
|
4
|
-
def
|
4
|
+
def initialize(body:)
|
5
|
+
@body = body
|
6
|
+
end
|
7
|
+
def handle
|
5
8
|
begin
|
6
|
-
parsed = JSON.parse(body.read)
|
9
|
+
parsed = JSON.parse(@body.read)
|
7
10
|
Brut.container.instrumentation.add_attributes(parsed.merge(prefix: "brut.csp-reporting"))
|
8
11
|
rescue => ex
|
9
12
|
Brut.container.instrumentation.record_exception(ex)
|
@@ -65,12 +65,16 @@ class Brut::FrontEnd::Handlers::InstrumentationHandler < Brut::FrontEnd::Handler
|
|
65
65
|
def as_carrier = { "traceparent" => @value }
|
66
66
|
end
|
67
67
|
|
68
|
-
def
|
69
|
-
|
70
|
-
|
68
|
+
def initialize(http_tracestate:, http_traceparent:)
|
69
|
+
@http_tracestate = http_tracestate
|
70
|
+
@http_traceparent = http_traceparent
|
71
|
+
end
|
72
|
+
def handle
|
73
|
+
traceparent = TraceParent.from_header(@http_traceparent)
|
74
|
+
span = Span.from_header(@http_tracestate)
|
71
75
|
|
72
76
|
if span.nil? || traceparent.nil?
|
73
|
-
SemanticLogger[self.class].info "Missing traceparent or span: #{http_tracestate}, #{http_traceparent}"
|
77
|
+
SemanticLogger[self.class].info "Missing traceparent or span: #{@http_tracestate}, #{@http_traceparent}"
|
74
78
|
return http_status(400)
|
75
79
|
end
|
76
80
|
|
@@ -5,9 +5,13 @@
|
|
5
5
|
# {Brut::FrontEnd::Session#http_accept_language=} *only* if the `Accept-Language` header did not provide a value that is supported by
|
6
6
|
# the app.
|
7
7
|
class Brut::FrontEnd::Handlers::LocaleDetectionHandler < Brut::FrontEnd::Handler
|
8
|
-
def
|
8
|
+
def initialize(body:,session:)
|
9
|
+
@body = body
|
10
|
+
@session = session
|
11
|
+
end
|
12
|
+
def handle
|
9
13
|
begin
|
10
|
-
parsed = JSON.parse(body.read)
|
14
|
+
parsed = JSON.parse(@body.read)
|
11
15
|
|
12
16
|
Brut.container.instrumentation.add_attributes(
|
13
17
|
prefix: "brut.locale-detection",
|
@@ -19,9 +23,9 @@ class Brut::FrontEnd::Handlers::LocaleDetectionHandler < Brut::FrontEnd::Handler
|
|
19
23
|
locale = parsed["locale"]
|
20
24
|
timezone = parsed["timeZone"]
|
21
25
|
|
22
|
-
session.timezone_from_browser = timezone
|
23
|
-
if
|
24
|
-
session.http_accept_language = Brut::I18n::HTTPAcceptLanguage.from_browser(locale)
|
26
|
+
@session.timezone_from_browser = timezone
|
27
|
+
if !@session.http_accept_language.known?
|
28
|
+
@session.http_accept_language = Brut::I18n::HTTPAcceptLanguage.from_browser(locale)
|
25
29
|
end
|
26
30
|
end
|
27
31
|
rescue => ex
|
@@ -1,7 +1,10 @@
|
|
1
1
|
# Used in development to handle a defined route but a missing page. This arranges to render a nicer error page than the default.
|
2
2
|
class Brut::FrontEnd::Handlers::MissingHandler < Brut::FrontEnd::Handler
|
3
|
-
def
|
4
|
-
|
3
|
+
def initialize(route:)
|
4
|
+
@route = route
|
5
|
+
end
|
6
|
+
def handle
|
7
|
+
Brut::FrontEnd::Pages::MissingPage.new(route: @route)
|
5
8
|
end
|
6
9
|
|
7
10
|
class Form < Brut::FrontEnd::Form
|
data/lib/brut/front_end/page.rb
CHANGED
@@ -35,12 +35,12 @@ class Brut::FrontEnd::Page < Brut::FrontEnd::Component
|
|
35
35
|
# redirect the user or produce an error.
|
36
36
|
#
|
37
37
|
# @return [URI|Brut::FrontEnd::HttpStatus|Object] If you return a `URI` (mostly likely by returning the result of calling {Brut::FrontEnd::HandlingResults#redirect_to}), the user is redirected and no HTML is generated. If you return a {Brut::FrontEnd::HttpStatus} (mostly likely by returning the result of calling {Brut::FrontEnd::HandlingResults#http_status}), HTML generation is skipped and that status is returned with no content. If anything else is returned, HTML is generated normal.
|
38
|
-
def
|
38
|
+
def before_generate = nil
|
39
39
|
|
40
|
-
# Core method of this class. Do not override. This handles the use of {#
|
40
|
+
# Core method of this class. Do not override. This handles the use of {#before_generate} and is what Brut
|
41
41
|
# calls to possibly render the page.
|
42
42
|
def handle!
|
43
|
-
case
|
43
|
+
case before_generate
|
44
44
|
in URI => uri
|
45
45
|
uri
|
46
46
|
in Brut::FrontEnd::HttpStatus => http_status
|
@@ -72,9 +72,6 @@ class Brut::FrontEnd::Page < Brut::FrontEnd::Component
|
|
72
72
|
# Convienience method for {.page_name}.
|
73
73
|
def page_name = self.class.page_name
|
74
74
|
|
75
|
-
# @!visibility private
|
76
|
-
def component_name = raise Brut::Framework::Errors::Bug,"#{self.class} is not a component"
|
77
|
-
|
78
75
|
private
|
79
76
|
|
80
77
|
# Locates the layout class and uses it to render itself, along
|
@@ -88,6 +85,7 @@ private
|
|
88
85
|
"layout"
|
89
86
|
].join("_")).camelize
|
90
87
|
)
|
88
|
+
Brut.container.instrumentation.add_prefixed_attributes("brut", layout_class: layout_class)
|
91
89
|
render layout_class.new(page_name:,&block)
|
92
90
|
end
|
93
91
|
|
@@ -112,12 +112,13 @@ class Brut::FrontEnd::RequestContext
|
|
112
112
|
# @param [Class] klass a class that is to be instantiated entirely by the contents of this `RequestContext`.
|
113
113
|
# @param [Hash] request_params Query string parameters provided by Rack.
|
114
114
|
# @param [Brut::FrontEnd::Routing::Route] route the route that triggered the request.
|
115
|
+
# @param [Brut::FrontEnd::Form] form the form, if available
|
115
116
|
# @return [Hash] can be splatted to keyword arguments and passed to the constructor of `klass`
|
116
117
|
#
|
117
118
|
# @raise [ArgumentError] if the constructor has any non-keyword arguments, or if any required keyword argument is
|
118
119
|
# not present in this `RequestContext`.
|
119
|
-
def as_constructor_args(klass, request_params:, route:nil)
|
120
|
-
args_for_method(method: klass.instance_method(:initialize), request_params:, form:
|
120
|
+
def as_constructor_args(klass, request_params:, route:nil, form: nil)
|
121
|
+
args_for_method(method: klass.instance_method(:initialize), request_params:, form: , route:)
|
121
122
|
end
|
122
123
|
|
123
124
|
# Based on `object`' method, returns a Hash that maps all keywords it requires to the values stored in this
|
@@ -6,43 +6,66 @@
|
|
6
6
|
# * {Brut::I18n::ForCLI} for CLI apps
|
7
7
|
# * {Brut::I18n::ForBackEnd} for back-end classes that aren't generating HTML
|
8
8
|
#
|
9
|
+
# This module assumes the existence of a three-method protocol that's used for HTML escaping in an
|
10
|
+
# HTML-generating web context:
|
11
|
+
#
|
12
|
+
# * `capture` accepts the block yieled to {#t} and returns whatever it generates. This needs to exist
|
13
|
+
# because Phlex's API renders to an internal buffer by default. This module needs to allow Phlex
|
14
|
+
# API methods to render to a different buffer.
|
15
|
+
# * `safe` accepts a string and returns a string that is presumed to be HTML safe.
|
16
|
+
# * `html_escape` accepts a string and returns a string that is HTML escaped.
|
17
|
+
#
|
18
|
+
# This module does not implement these methods and assumes that either the class using this module will
|
19
|
+
# implement them or that a submodule being used does. All submodules provided by Brut provide implementations,
|
20
|
+
# so this information is only relevant if you are using this module directly.
|
9
21
|
module Brut::I18n::BaseMethods
|
10
22
|
|
11
23
|
# Access a translation and insert interpolated elemens as needed. This will use the provided key to determine
|
12
|
-
# the actual full key to the translation, as described below.
|
13
|
-
#
|
14
|
-
# values *are* HTML escaped, so external input is safe to provide.
|
15
|
-
#
|
16
|
-
# This method also may take a block, and the results of the block are inserted into the `%{block}`
|
17
|
-
# interpolation value in the i18n string, if it's present.
|
24
|
+
# the actual full key to the translation, as described below. See {Brut::I18n::ForHTML#t} for details
|
25
|
+
# on how this works in the context of a {Brut::FrontEnd::Component} or {Brut::FrontEnd::Page}.
|
18
26
|
#
|
19
27
|
# Any missing interpolation will result in an exception, *except* for the value `field`. When
|
20
28
|
# a string has `%{field}` in it, but `field:` is omitted in this call, the value for
|
21
|
-
# `"
|
29
|
+
# `"cv.this_field"` is used. This value, in English, is "this field", so a call
|
22
30
|
# to `t("email.required")` would generate `"This field is required"`, while a call
|
23
31
|
# to `t("email.required", field: "E-mail address")` would generate `"E-mail address is required"`.
|
24
32
|
#
|
25
33
|
# @param [String,Symbol,Array<String>,Array<Symbol>] key used to create one or more keys to be translated.
|
26
|
-
# This value's behavior
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
34
|
+
# This value's behavior balances predictabilitiy with what key is used and some flexibilty
|
35
|
+
# to allow page– or component–specific translations when needed, and fallbacks when not.
|
36
|
+
#
|
37
|
+
# When an array if given, the values are turned into strings and joined with a "." to
|
38
|
+
# form a full key.
|
39
|
+
#
|
40
|
+
# Depending on what class this module is mixed into, additional keys will be tried:
|
41
|
+
#
|
42
|
+
# * If this is a page, `pages.«page_name».` will be prepended and tried before the key passed in.
|
43
|
+
# If the `pages.«page_name»` version is not found, the exact key passed in is checked.
|
44
|
+
# * If this is a page private component, `pages.«page_name».` will be prepended and tried before
|
45
|
+
# the key passed in. The value for `«page_name»` is determined by the outer class that this
|
46
|
+
# component is a part of.
|
47
|
+
# * If this is a component (include if it is a page private component),
|
48
|
+
# `components.«component_name».` will be prepended and tried before the key passed in.
|
49
|
+
# If the `components.«component_name»` version is not found, the exact key passed in is checked.
|
50
|
+
#
|
51
|
+
# The priority of the keys are as follows:
|
52
|
+
#
|
53
|
+
# 1. Component key is checked (unless this is a page)
|
54
|
+
# 2. Page key is checked (unless this is a non-page private component)
|
55
|
+
# 3. The literal key passed-in is checked
|
56
|
+
#
|
57
|
+
# If no value is found for any key an exception is raised.
|
58
|
+
#
|
59
|
+
# @param [Hash] interpolated_values values to use for interpolation of the key's translation. Note that if
|
60
|
+
# `:block` is part of this has, you may not pass a block to this method. Note also
|
61
|
+
# that `:count` can be used if the key is expected to be pluralized. This value
|
62
|
+
# is required for keys that are designed for pluralization. See examples below.
|
41
63
|
# @option interpolated_values [Numeric] count Special interpolation to control pluralization.
|
42
|
-
# @
|
43
|
-
#
|
64
|
+
# @option interpolated_values [String] block Value to use for `%{block}`. If this is used, a block may not be
|
65
|
+
# yielded.
|
66
|
+
# @yield If a block is passed, it is used for the value of `%{block}`. No parameters are yielded to the block.
|
44
67
|
# @yieldreturn [String] The value to use for the `%{block}` interpolation value. There is some nuance to
|
45
|
-
# how this works. The value returned is given to `capture`, and that value
|
68
|
+
# how this works. The value returned is given to `capture`, and *that* value
|
46
69
|
# is given to `safe`. Outside of an HTML-rendering context, these methods
|
47
70
|
# simply pass through the contents of the block. In an HTML-rendering
|
48
71
|
# context, however, these methods are assumed to be from
|
@@ -57,25 +80,17 @@ module Brut::I18n::BaseMethods
|
|
57
80
|
# @example Simplest usage
|
58
81
|
# # in your translations file
|
59
82
|
# en: {
|
60
|
-
#
|
61
|
-
# hello: "Hi!"
|
62
|
-
# },
|
63
|
-
# formalized: {
|
64
|
-
# hello: "Greetings!"
|
65
|
-
# }
|
83
|
+
# hello: "Hi!"
|
66
84
|
# }
|
67
85
|
# # in your code
|
68
86
|
# t(:hello) # => Hi!
|
69
|
-
# t("formalized.hello") # => Greetings!
|
70
87
|
#
|
71
88
|
# @example Using an array for the key
|
72
89
|
# # in your translations file
|
73
90
|
# en: {
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
# }
|
78
|
-
# },
|
91
|
+
# actions: {
|
92
|
+
# edit: "Make an edit"
|
93
|
+
# }
|
79
94
|
# }
|
80
95
|
# # in your code
|
81
96
|
# t([:actions, :edit]) # => Make an edit
|
@@ -83,9 +98,7 @@ module Brut::I18n::BaseMethods
|
|
83
98
|
# @example Using page:
|
84
99
|
# # in your translations file
|
85
100
|
# en: {
|
86
|
-
#
|
87
|
-
# new_widget: "Make a New Widget",
|
88
|
-
# },
|
101
|
+
# new_widget: "Make a New Widget",
|
89
102
|
# pages: {
|
90
103
|
# HomePage: {
|
91
104
|
# new_widget: "Create new Widget"
|
@@ -96,28 +109,61 @@ module Brut::I18n::BaseMethods
|
|
96
109
|
# },
|
97
110
|
# }
|
98
111
|
# # in your code for HomePage
|
99
|
-
# t(
|
112
|
+
# t(:new_widget) # => Create new Widget
|
100
113
|
# # in your code for WidgetsPage
|
101
|
-
# t(
|
114
|
+
# t(:new_widget) # => Create New
|
102
115
|
# # in your code for SomeOtherPage
|
103
|
-
# t(
|
116
|
+
# t(:new_widget) # => Make a New Widget
|
104
117
|
#
|
105
|
-
# @example Using
|
118
|
+
# @example Using in a component
|
106
119
|
# # in your translations file
|
107
120
|
# en: {
|
121
|
+
# status: {
|
122
|
+
# ready: "Available",
|
123
|
+
# stalled: "Stalled",
|
124
|
+
# completed: "Done",
|
125
|
+
# },
|
126
|
+
# components: {
|
127
|
+
# TagComponent: {
|
128
|
+
# status: {
|
129
|
+
# ready: "Ready",
|
130
|
+
# stalled: "Waiting",
|
131
|
+
# }
|
132
|
+
# },
|
133
|
+
# },
|
134
|
+
# }
|
135
|
+
# # in your code for TagComponent
|
136
|
+
# t(page: [ :status, :ready ]) # => Ready
|
137
|
+
# t(page: [ :status, :completed ]) # => Done
|
138
|
+
# # in your code for StatusComponent
|
139
|
+
# t(page: [ :status, :ready ]) # => Available
|
140
|
+
# t(page: [ :status, :completed ]) # => Done
|
141
|
+
#
|
142
|
+
# @example Using in a page-private component
|
143
|
+
# # in your translations file
|
144
|
+
# en: {
|
145
|
+
# status: {
|
146
|
+
# ready: "Available",
|
147
|
+
# stalled: "Stalled",
|
148
|
+
# completed: "Done",
|
149
|
+
# },
|
108
150
|
# pages: {
|
109
151
|
# WidgetsPage: {
|
110
|
-
# new_widget: "Create New"
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
152
|
+
# new_widget: "Create New",
|
153
|
+
# nevermind: "Don't Create One",
|
154
|
+
# },
|
155
|
+
# }
|
156
|
+
# components: {
|
157
|
+
# "WidgetsPage::WidgetComponent": {
|
158
|
+
# new_widget: "Make New Widget",
|
114
159
|
# },
|
115
160
|
# },
|
116
161
|
# }
|
117
|
-
# # in your code for
|
118
|
-
# t(page:
|
162
|
+
# # in your code for WidgetsPage::WidgetComponent
|
163
|
+
# t(page: :new_widget) # => Make New Widget
|
164
|
+
# t(page: :nevermind) # => Don't Create One
|
119
165
|
#
|
120
|
-
# @example Using a block
|
166
|
+
# @example Using a block in a page or component
|
121
167
|
# # in your translations file
|
122
168
|
# en: {
|
123
169
|
# greeting: "Hello there %{name}, you may %{block}",
|
@@ -140,42 +186,35 @@ module Brut::I18n::BaseMethods
|
|
140
186
|
# contact support
|
141
187
|
# </a>
|
142
188
|
# </h1>
|
143
|
-
def t(key
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
189
|
+
def t(key,**interpolated_values,&block)
|
190
|
+
keys_to_check = []
|
191
|
+
key = Array(key).join('.')
|
192
|
+
is_page_private_component = self.kind_of?(Brut::FrontEnd::Component) &&
|
193
|
+
self.page_private?
|
194
|
+
is_page = self.kind_of?(Brut::FrontEnd::Page)
|
195
|
+
is_component = self.kind_of?(Brut::FrontEnd::Component) && !is_page
|
148
196
|
|
149
|
-
|
150
|
-
|
151
|
-
end
|
152
|
-
|
153
|
-
subkey = nil
|
154
|
-
if page
|
155
|
-
subkey = Array(page).join(".")
|
156
|
-
key = ["pages.#{self.page_name}.#{subkey}"]
|
157
|
-
elsif component
|
158
|
-
subkey = Array(component).join(".")
|
159
|
-
key = ["components.#{self.component_name}.#{subkey}"]
|
160
|
-
else
|
161
|
-
raise ArgumentError, "If you omit an explicit key, you must specify page or component"
|
162
|
-
end
|
163
|
-
key << "general.#{subkey}"
|
164
|
-
else
|
165
|
-
key = Array(key).join('.')
|
166
|
-
key = [key,"general.#{key}"]
|
197
|
+
if is_component
|
198
|
+
keys_to_check << "components.#{self.component_name}.#{key}"
|
167
199
|
end
|
200
|
+
if is_page
|
201
|
+
keys_to_check << "pages.#{self.page_name}.#{key}"
|
202
|
+
elsif is_page_private_component
|
203
|
+
keys_to_check << "pages.#{self.containing_page_name}.#{key}"
|
204
|
+
end
|
205
|
+
keys_to_check << key
|
206
|
+
|
168
207
|
if !block.nil?
|
169
|
-
if
|
208
|
+
if interpolated_values[:block]
|
170
209
|
raise ArgumentError,"t was given a block and a block: param. You can't do both "
|
171
210
|
end
|
172
211
|
block_contents = safe(capture(&block))
|
173
|
-
|
212
|
+
interpolated_values[:block] = block_contents
|
174
213
|
end
|
175
|
-
t_direct(key
|
214
|
+
t_direct(keys_to_check,**interpolated_values.merge(key_given: key))
|
176
215
|
rescue I18n::MissingInterpolationArgument => ex
|
177
216
|
if ex.key.to_s == "block"
|
178
|
-
raise ArgumentError,"One of the keys #{key.join(", ")} contained a %{block} interpolation value: '#{ex.string}'. This means you must
|
217
|
+
raise ArgumentError,"One of the keys #{key.join(", ")} contained a %{block} interpolation value: '#{ex.string}'. This means you must yield a block to `t`"
|
179
218
|
else
|
180
219
|
raise
|
181
220
|
end
|
@@ -186,7 +225,7 @@ module Brut::I18n::BaseMethods
|
|
186
225
|
end
|
187
226
|
|
188
227
|
def this_field_value
|
189
|
-
@__this_field_value ||= ::I18n.t("
|
228
|
+
@__this_field_value ||= ::I18n.t("cv.this_field", raise: true)
|
190
229
|
end
|
191
230
|
|
192
231
|
# Directly access translations without trying to be smart about deriving the key. This is useful
|
@@ -194,28 +233,43 @@ module Brut::I18n::BaseMethods
|
|
194
233
|
#
|
195
234
|
# @param [Array<String>,Array<Symbol>] keys list of keys representing what is to be translated. The
|
196
235
|
# first key found will be used. If no key in the list is found
|
197
|
-
# will raise a I18n::MissingTranslation
|
236
|
+
# will raise a I18n::MissingTranslation.
|
198
237
|
# @param [Hash] interpolated_values value to use for interpolation of the key's translation
|
199
238
|
# @option interpolated_values [Numeric] count Special interpolation to control pluralization.
|
239
|
+
# @option interpolated_values [String|Symbol] key_given If included, this is not used for interpolation, but
|
240
|
+
# will be used in error messages to represent the key
|
241
|
+
# given to `t`.
|
200
242
|
#
|
201
243
|
# @raise [I18n::MissingTranslation] if no translation is found
|
202
244
|
# @raise [I18n::MissingInterpolationArgument] if interpolation arguments are missing, or if the key
|
203
245
|
# has pluralizations and no count: was given
|
204
246
|
def t_direct(keys,interpolated_values={})
|
205
247
|
keys = Array(keys).map(&:to_sym)
|
248
|
+
key_given = interpolated_values.delete(:key_given)
|
206
249
|
default_interpolated_values = {
|
207
250
|
field: this_field_value,
|
208
251
|
}
|
209
252
|
escaped_interpolated_values = interpolated_values.map { |key,value|
|
210
253
|
if value.kind_of?(String)
|
211
|
-
[ key,
|
254
|
+
[ key, html_escape(value) ]
|
212
255
|
else
|
213
256
|
[ key, value ]
|
214
257
|
end
|
215
258
|
}.to_h
|
216
259
|
result = ::I18n.t(keys.first, default: keys[1..-1],raise: true, **default_interpolated_values.merge(escaped_interpolated_values))
|
217
260
|
if result.kind_of?(Hash)
|
218
|
-
|
261
|
+
incorrect_pluralization = result.keys.none? { |key| key == :one }
|
262
|
+
if incorrect_pluralization
|
263
|
+
key_message = if key_given
|
264
|
+
"Key '#{key_given}'"
|
265
|
+
else
|
266
|
+
"One of the keys"
|
267
|
+
end
|
268
|
+
raise Brut::Framework::Errors::Bug,
|
269
|
+
"#{key_message} resulted in a Hash that doesn't appear to be created for pluralizations. This means that you may have given a key expecting it to map to a translation but it is actually a namespace for other keys. Please adjust your translations file to avoid this situation. Keys checked:\n#{keys.join(", ")}\nSub keys found:\n#{result.keys.join(', ')}"
|
270
|
+
else
|
271
|
+
raise I18n::MissingInterpolationArgument.new(:count,interpolated_values,keys.join(","))
|
272
|
+
end
|
219
273
|
end
|
220
274
|
result
|
221
275
|
end
|
data/lib/brut/i18n/for_cli.rb
CHANGED
data/lib/brut/i18n/for_html.rb
CHANGED
@@ -1,12 +1,40 @@
|
|
1
1
|
# I18n for components or pages, which are assumed to be Phlex components.
|
2
|
-
#
|
3
|
-
#
|
2
|
+
# This will do HTML escaping as follows:
|
3
|
+
#
|
4
|
+
# * Interpolated values are always HTML-escaped
|
5
|
+
# * When a block is used, that value is assumed to be safe HTML,
|
6
|
+
# and generated outside the current Phlex context. It's value is
|
7
|
+
# captured (via `#capture`) and then declared HTML safe by being
|
8
|
+
# passed to `#safe`.
|
9
|
+
#
|
10
|
+
# Unless you put HTML injections into your translations file, this should result
|
11
|
+
# in safe HTML in any translation.
|
12
|
+
#
|
13
|
+
# This module provides two features that aren't part of {#Brut::I18n::BaseMethods}:
|
14
|
+
#
|
15
|
+
# * {#t} calls `#safe` on its return value, indicating that the string is safe. To use
|
16
|
+
# this string in a Phlex view, you *must* call `#raw` and pass it the string.
|
17
|
+
# * {#html_escape} is implemented to escape values it's given.
|
18
|
+
#
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# class StatusComponent < AppComponent
|
22
|
+
# def initialize(status:)
|
23
|
+
# @status = status
|
24
|
+
# end
|
25
|
+
# def view_template
|
26
|
+
# div do
|
27
|
+
# raw(
|
28
|
+
# t( [ :status, @status ] )
|
29
|
+
# )
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
# end
|
4
33
|
#
|
5
|
-
# * `safe` to accept a string and return a string.
|
6
|
-
# * `capture` to accept a block and return its contents as a string.
|
7
34
|
module Brut::I18n::ForHTML
|
8
35
|
include Brut::I18n::BaseMethods
|
9
36
|
def t(...)
|
10
37
|
safe(super)
|
11
38
|
end
|
39
|
+
def html_escape(value) = CGI.escapeHTML(value)
|
12
40
|
end
|
@@ -63,7 +63,7 @@ class Brut::Instrumentation::OpenTelemetry
|
|
63
63
|
# @param [Exception] ex the exception to record.
|
64
64
|
# @param [Hash] attributes any attributes to attach that will show up in your OTel provider
|
65
65
|
# @raise [Exception] the exception passed in.
|
66
|
-
def record_and_reraise_exception(ex,attributes=nil)
|
66
|
+
def record_and_reraise_exception!(ex,attributes=nil)
|
67
67
|
reecord_exception(ex,attributes)
|
68
68
|
raise ex
|
69
69
|
end
|
@@ -71,13 +71,23 @@ class Brut::Instrumentation::OpenTelemetry
|
|
71
71
|
|
72
72
|
# Adds attributes to the span, converting the hash or keyword arguments to strings. This will use
|
73
73
|
# the app's Otel prefix for all attributes, so you do not have to prefix them.
|
74
|
-
# If you need to set standard attributes, you should use {
|
74
|
+
# If you need to set standard attributes, you should use {#add_prefixed_attributes} instead.
|
75
75
|
# @param [Hash] attributes any attributes to attach to the event.
|
76
76
|
def add_attributes(attributes)
|
77
77
|
current_span = OpenTelemetry::Trace.current_span
|
78
78
|
current_span.add_attributes(NormalizedAttributes.new(:detect,attributes).to_h)
|
79
79
|
end
|
80
80
|
|
81
|
+
# Adds attributes to the span, prefixing each key with the given prefix, then converting the hash or keyword arguments to strings. For example, if the prefix is 'my_app' and you add the attributes 'type' and 'reason', the actual attribute names will be 'my_app.type' and 'my_app.reason'.
|
82
|
+
#
|
83
|
+
# @see #add_attributes
|
84
|
+
def add_prefixed_attributes(prefix,attributes)
|
85
|
+
current_span = OpenTelemetry::Trace.current_span
|
86
|
+
current_span.add_attributes(
|
87
|
+
NormalizedAttributes.new(prefix,attributes).to_h
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
81
91
|
private
|
82
92
|
|
83
93
|
class NormalizedAttributes
|
data/lib/brut/sinatra_helpers.rb
CHANGED
@@ -179,16 +179,23 @@ module Brut::SinatraHelpers
|
|
179
179
|
form_class: form_class,
|
180
180
|
)
|
181
181
|
|
182
|
-
handler = handler_class.new
|
183
182
|
form = if form_class.nil?
|
184
183
|
nil
|
185
184
|
else
|
186
185
|
form_class.new(params: params)
|
187
186
|
end
|
188
187
|
|
189
|
-
|
188
|
+
constructor_args = Brut::FrontEnd::RequestContext.current.as_constructor_args(
|
189
|
+
handler_class,
|
190
|
+
request_params: params,
|
191
|
+
route: brut_route,
|
192
|
+
form: form,
|
193
|
+
)
|
194
|
+
|
195
|
+
handler = handler_class.new(**constructor_args)
|
190
196
|
|
191
|
-
result = handler.handle!
|
197
|
+
result = handler.handle!
|
198
|
+
span.add_prefixed_attributes("brut", result_class: result.class)
|
192
199
|
|
193
200
|
case result
|
194
201
|
in URI => uri
|