brut 0.0.20 → 0.0.22
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/{doc-src → brutrb.com}/keyword-injection.md +122 -68
- 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/back_end/seed_data.rb +19 -2
- data/lib/brut/back_end/sidekiq/middlewares/server.rb +2 -1
- data/lib/brut/back_end/sidekiq/middlewares.rb +2 -1
- data/lib/brut/back_end/sidekiq.rb +2 -1
- data/lib/brut/back_end/validator.rb +5 -1
- data/lib/brut/back_end.rb +4 -2
- data/lib/brut/cli/app_runner.rb +1 -1
- data/lib/brut/cli/apps/test.rb +5 -0
- data/lib/brut/cli.rb +4 -3
- data/lib/brut/factory_bot.rb +0 -5
- data/lib/brut/framework/app.rb +70 -5
- data/lib/brut/framework/config.rb +5 -3
- data/lib/brut/framework/container.rb +3 -2
- data/lib/brut/framework/errors.rb +12 -4
- data/lib/brut/framework/mcp.rb +58 -1
- data/lib/brut/framework/project_environment.rb +6 -2
- data/lib/brut/framework.rb +1 -1
- data/lib/brut/front_end/component.rb +69 -71
- 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} +7 -9
- 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/layout.rb +16 -0
- data/lib/brut/front_end/page.rb +52 -29
- data/lib/brut/front_end/request_context.rb +3 -2
- data/lib/brut/front_end/routing.rb +5 -1
- data/lib/brut/front_end.rb +4 -13
- data/lib/brut/i18n/base_methods.rb +167 -79
- data/lib/brut/i18n/for_back_end.rb +4 -0
- data/lib/brut/i18n/for_cli.rb +4 -0
- data/lib/brut/i18n/for_html.rb +32 -4
- data/lib/brut/i18n/http_accept_language.rb +47 -0
- data/lib/brut/instrumentation/open_telemetry.rb +36 -1
- data/lib/brut/instrumentation.rb +3 -5
- data/lib/brut/sinatra_helpers.rb +11 -3
- data/lib/brut/spec_support/component_support.rb +30 -16
- data/lib/brut/spec_support/e2e_support.rb +1 -1
- data/lib/brut/spec_support/e2e_test_server.rb +3 -0
- data/lib/brut/spec_support/general_support.rb +3 -0
- data/lib/brut/spec_support/handler_support.rb +6 -1
- data/lib/brut/spec_support/matcher.rb +1 -0
- data/lib/brut/spec_support/matchers/be_page_for.rb +1 -0
- data/lib/brut/spec_support/matchers/have_html_attribute.rb +1 -0
- data/lib/brut/spec_support/matchers/have_i18n_string.rb +2 -5
- data/lib/brut/spec_support/matchers/have_link_to.rb +1 -0
- data/lib/brut/spec_support/matchers/have_redirected_to.rb +1 -0
- data/lib/brut/spec_support/matchers/have_rendered.rb +1 -0
- data/lib/brut/spec_support/matchers/have_returned_rack_response.rb +44 -0
- data/lib/brut/spec_support.rb +1 -1
- data/lib/brut/version.rb +1 -1
- data/lib/brut.rb +5 -4
- data/lib/sequel/extensions/brut_migrations.rb +1 -1
- metadata +648 -13
- data/doc-src/architecture.md +0 -102
- data/doc-src/assets.md +0 -98
- data/doc-src/forms.md +0 -214
- data/doc-src/handlers.md +0 -83
- data/doc-src/javascript.md +0 -265
- data/doc-src/pages.md +0 -210
- data/doc-src/route-hooks.md +0 -59
- data/lib/brut/front_end/components/inputs/select.rb +0 -117
@@ -0,0 +1,98 @@
|
|
1
|
+
:root {
|
2
|
+
--ff-sans: "Helvetica Neue", Helvetica, sans-serif;
|
3
|
+
}
|
4
|
+
h1, h2, h3, h4, h5, h6 {
|
5
|
+
margin: 0;
|
6
|
+
}
|
7
|
+
p:not([class]),
|
8
|
+
li:not([class]) {
|
9
|
+
max-width: var(--tw);
|
10
|
+
line-height: 1.75;
|
11
|
+
color: var(--gray-400);
|
12
|
+
}
|
13
|
+
a:not([class]),
|
14
|
+
a:not([class]):visited {
|
15
|
+
color: var(--blue-300);
|
16
|
+
}
|
17
|
+
h1 {
|
18
|
+
font-size: var(--fs-6);
|
19
|
+
color: var(--gray-200);
|
20
|
+
}
|
21
|
+
h2 {
|
22
|
+
font-size: var(--fs-5);
|
23
|
+
color: var(--gray-200);
|
24
|
+
}
|
25
|
+
h3 {
|
26
|
+
font-size: var(--fs-3);
|
27
|
+
color: var(--gray-200);
|
28
|
+
}
|
29
|
+
nav h3 {
|
30
|
+
text-transform: uppercase;
|
31
|
+
font-weight: 300;
|
32
|
+
color: var(--gray-400);
|
33
|
+
letter-spacing: var(--ls);
|
34
|
+
}
|
35
|
+
nav ul {
|
36
|
+
list-style-type: none;
|
37
|
+
margin-top: var(--sp-2);
|
38
|
+
margin-bottom: var(--sp-2);
|
39
|
+
margin-right: 0;
|
40
|
+
margin-left: 0;
|
41
|
+
padding-bottom: var(--sp-2);
|
42
|
+
li {
|
43
|
+
line-height: var(--lh-copy);
|
44
|
+
margin-top: var(--sp-1);
|
45
|
+
margin-bottom: var(--sp-1);
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
dl.property-grid {
|
50
|
+
display: grid;
|
51
|
+
grid-template-columns: max-content 1fr;
|
52
|
+
gap: var(--sp-2);
|
53
|
+
margin: 0;
|
54
|
+
dt {
|
55
|
+
font-weight: 600;
|
56
|
+
}
|
57
|
+
dd {
|
58
|
+
margin: 0;
|
59
|
+
}
|
60
|
+
}
|
61
|
+
|
62
|
+
pre.highlighted-code {
|
63
|
+
margin: 0;
|
64
|
+
padding: var(--sp-2);
|
65
|
+
background-color: var(--black);
|
66
|
+
color: var(--white);
|
67
|
+
border-radius: var(--bw-3);
|
68
|
+
}
|
69
|
+
|
70
|
+
.example {
|
71
|
+
pre.highlighted-code {
|
72
|
+
border-bottom-left-radius: 0;
|
73
|
+
border-bottom-right-radius: 0;
|
74
|
+
background-color: var(--green-200);
|
75
|
+
}
|
76
|
+
.example-demonstration {
|
77
|
+
padding: var(--sp-2);
|
78
|
+
border-bottom-left-radius: var(--bw-3);
|
79
|
+
border-bottom-right-radius: var(--bw-3);
|
80
|
+
border: solid thin var(--black);
|
81
|
+
background-color: var(--gray-800);
|
82
|
+
.class-being-demonstrated {
|
83
|
+
color: var(--white);
|
84
|
+
font-weight: 600;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
.see-also p {
|
90
|
+
margin: 0;
|
91
|
+
line-height: var(--lh-copy);
|
92
|
+
}
|
93
|
+
|
94
|
+
|
95
|
+
.ridiculous-liquid-glass-is-all-the-rage {
|
96
|
+
background: rgba(255, 255, 255, 0.85);
|
97
|
+
backdrop-filter: blur(3px);
|
98
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<body class="flex flex-column ff-sans ma-0 pa-0 h-100">
|
2
|
+
<header class="pos-sticky top-0 bg-gray-700 pa-3 z-5 shadow-2">
|
3
|
+
<div class="flex gap-3 justify-between items-center">
|
4
|
+
<h1><a href="<%= pathToBrutCSSRoot %>" class="black tdn">BrutCSS Reference Documentation</a></h1>
|
5
|
+
<ul class="lst-none pl-0 flex gap-2 justify-end items-center">
|
6
|
+
<form class="flex items-center gap-1 mr-3">
|
7
|
+
<label>
|
8
|
+
<input type="search" placeholder="e.g. padding-left" class="pa-2 br-2 ba bc-gray-600 bg-white-ish gray-200">
|
9
|
+
<span class="sr-only">Search term</span>
|
10
|
+
</label>
|
11
|
+
<button class="ph-3 pv-2 bg-white gray-100 ba bc-gray-500 br-3 hover-bg-gray-800 pointer flex items-center justify-between">
|
12
|
+
<span class="mr-2">Search</span>
|
13
|
+
<kbd>⌘</kbd>
|
14
|
+
<kbd>/</kbd>
|
15
|
+
</button>
|
16
|
+
</form>
|
17
|
+
<li><a href="/" class="red-200 tdn hover-tdu">BrutRB</a></li>
|
18
|
+
<span aria-hidden="true">·</span>
|
19
|
+
<li><a href="/brut-js" class="gray-200 tdn hover-tdu">BrutJS</a></li>
|
20
|
+
<span aria-hidden="true">·</span>
|
21
|
+
<li><a href="https://github.com/thirdtank/brut/tree/main/brut-css" class="gray-200 tdn hover-tdu">Code</a></li>
|
22
|
+
</ul>
|
23
|
+
</div>
|
24
|
+
</header>
|
25
|
+
<main class="flex overflow-hidden flex-grow-1 flex-shrink-1 flex-basis-0 pos-relative">
|
26
|
+
<nav class="overflow-y-auto ph-3 pb-2 pt-4 w-20 bg-gray-800 gray-200 h-100">
|
27
|
+
<%- include("nav.html.ejs") %>
|
28
|
+
</nav>
|
29
|
+
<section class="overflow-y-auto pt-4 h-100 flex-grow-1 flex-shrink-1 flex-basis-0 flex flex-column">
|
30
|
+
<div class="ph-3 pv-2 flex items-start gap-2 justify-between">
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% nav.forEach( (navSection) => { %>
|
2
|
+
<h3><%= navSection.title.toString() %></h3>
|
3
|
+
<ul class="pl-3">
|
4
|
+
<% navSection.items.forEach( ({page}) => { %>
|
5
|
+
<li>
|
6
|
+
<a class="black-ish tdu tdn-ns hover-tdu-ns" href="<%= pathToBrutCSSRoot %>/<%= page.uri %>"><%= page.title.toString() %></a>
|
7
|
+
</li>
|
8
|
+
<% }) %>
|
9
|
+
</ul>
|
10
|
+
<% }) %>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html class="ma-0 pa-0 h-100" lang="en">
|
3
|
+
<%- include("includes/head.html.ejs") %>
|
4
|
+
<%- include("includes/body-and-header.html.ejs") %>
|
5
|
+
<article>
|
6
|
+
<h2>A Utility-Based CSS Framework For Getting Started</h2>
|
7
|
+
<div role="status" class="mt-4 pa-3 br-3 ba measure bc-red-400 bg-red-800 red-400 f3 fw-6 flex items-center gap-3">
|
8
|
+
<span role="none" class="f-4 f-l">⚠️</span>
|
9
|
+
<div>
|
10
|
+
<p class="red-400 p ma-0">
|
11
|
+
This documentation is in somewhat rough shape. What information is here <strong>is</strong>
|
12
|
+
accurate, however it is not as complete or elucidating as it could be.
|
13
|
+
</p>
|
14
|
+
<p class="red-400 p ma-0 mt-2">
|
15
|
+
The <code>.css</code>, however, is much more stable and should be considered as a release candidate, unlikely
|
16
|
+
to be given breaking changes in the near future.
|
17
|
+
</p>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
<p>
|
21
|
+
BrutCSS lets you get started quickly designing in the browser. It does this with classes whose names are based on the CSS attributes and values they will apply. You can quickly learn BrutCSS to start designing in minutes.
|
22
|
+
</p>
|
23
|
+
<p>
|
24
|
+
BrutCSS does <strong>not</strong> replace the use of CSS. BrutCSS has no build step, no derived classes, and does not attempt to provide a class for every CSS attribute/value combination.
|
25
|
+
</p>
|
26
|
+
<p>
|
27
|
+
BrutCSS knows you know CSS, knows you know your web framework, and wants you to use it.
|
28
|
+
</p>
|
29
|
+
</article>
|
30
|
+
<%- include("includes/footer-and-rest.html.ejs") %>
|
31
|
+
</html>
|
32
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
code[class*=language-],pre[class*=language-]{color:#fff;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;text-shadow:0 -.1em .2em #000;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}:not(pre)>code[class*=language-],pre[class*=language-]{background:#141414}pre[class*=language-]{border-radius:.5em;border:.3em solid #545454;box-shadow:1px 1px .5em #000 inset;margin:.5em 0;overflow:auto;padding:1em}pre[class*=language-]::-moz-selection{background:#27292a}pre[class*=language-]::selection{background:#27292a}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:hsla(0,0%,93%,.15)}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:hsla(0,0%,93%,.15)}:not(pre)>code[class*=language-]{border-radius:.3em;border:.13em solid #545454;box-shadow:1px 1px .3em -.1em #000 inset;padding:.15em .2em .05em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#777}.token.punctuation{opacity:.7}.token.namespace{opacity:.7}.token.boolean,.token.deleted,.token.number,.token.tag{color:#ce6849}.token.builtin,.token.constant,.token.keyword,.token.property,.token.selector,.token.symbol{color:#f9ed99}.language-css .token.string,.style .token.string,.token.attr-name,.token.attr-value,.token.char,.token.entity,.token.inserted,.token.operator,.token.string,.token.url,.token.variable{color:#909e6a}.token.atrule{color:#7385a5}.token.important,.token.regex{color:#e8c062}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.language-markup .token.attr-name,.language-markup .token.punctuation,.language-markup .token.tag{color:#ac885c}.token{position:relative;z-index:1}.line-highlight.line-highlight{background:hsla(0,0%,33%,.25);background:linear-gradient(to right,hsla(0,0%,33%,.1) 70%,hsla(0,0%,33%,0));border-bottom:1px dashed #545454;border-top:1px dashed #545454;margin-top:.75em;z-index:0}.line-highlight.line-highlight:before,.line-highlight.line-highlight[data-end]:after{background-color:#8693a6;color:#f4f1ef}
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class Logger {
|
2
|
+
static LEVELS = {
|
3
|
+
"debug": 0,
|
4
|
+
"info": 1,
|
5
|
+
"warn": 2,
|
6
|
+
"error": 3,
|
7
|
+
}
|
8
|
+
|
9
|
+
static instance = null
|
10
|
+
|
11
|
+
static debug(...args) {
|
12
|
+
this.instance.debug(...args)
|
13
|
+
}
|
14
|
+
static info(...args) {
|
15
|
+
this.instance.info(...args)
|
16
|
+
}
|
17
|
+
static log(...args) {
|
18
|
+
this.instance.log(...args)
|
19
|
+
}
|
20
|
+
static warn(...args) {
|
21
|
+
this.instance.warn(...args)
|
22
|
+
}
|
23
|
+
static error(...args) {
|
24
|
+
this.instance.error(...args)
|
25
|
+
}
|
26
|
+
|
27
|
+
constructor(argv0) {
|
28
|
+
this.prefix = `[ ${argv0} ]`
|
29
|
+
this.level = "warn"
|
30
|
+
}
|
31
|
+
|
32
|
+
set level(value) {
|
33
|
+
this.levelValue = this.constructor.LEVELS[value]
|
34
|
+
}
|
35
|
+
|
36
|
+
#addPrefix(args) {
|
37
|
+
if (typeof args[0] === "string") {
|
38
|
+
args[0] = `${this.prefix} ${args[0]}`
|
39
|
+
} else {
|
40
|
+
args.unshift(this.prefix)
|
41
|
+
}
|
42
|
+
return args
|
43
|
+
}
|
44
|
+
|
45
|
+
debug(...args) {
|
46
|
+
if (this.levelValue <= this.constructor.LEVELS["debug"]) {
|
47
|
+
console.debug(...this.#addPrefix(args))
|
48
|
+
}
|
49
|
+
}
|
50
|
+
info(...args) {
|
51
|
+
if (this.levelValue <= this.constructor.LEVELS["info"]) {
|
52
|
+
console.info(...this.#addPrefix(args))
|
53
|
+
}
|
54
|
+
}
|
55
|
+
log(...args) {
|
56
|
+
if (this.levelValue <= this.constructor.LEVELS["info"]) {
|
57
|
+
console.log(...this.#addPrefix(args))
|
58
|
+
}
|
59
|
+
}
|
60
|
+
warn(...args) {
|
61
|
+
if (this.levelValue <= this.constructor.LEVELS["warn"]) {
|
62
|
+
console.warn(...this.#addPrefix(args))
|
63
|
+
}
|
64
|
+
}
|
65
|
+
error(...args) {
|
66
|
+
if (this.levelValue <= this.constructor.LEVELS["error"]) {
|
67
|
+
console.error(...this.#addPrefix(args))
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}
|
71
|
+
export default Logger
|
@@ -0,0 +1,111 @@
|
|
1
|
+
import fs from "node:fs"
|
2
|
+
import path from "node:path"
|
3
|
+
import postcss from "postcss"
|
4
|
+
import postcssImport from "postcss-import"
|
5
|
+
|
6
|
+
import Logger from "./Logger.js"
|
7
|
+
import generateRootCustomPropertiesPlugin from "./post-css-plugins/generateRootCustomPropertiesPlugin.js"
|
8
|
+
import addMediaQueriesPlugin from "./post-css-plugins/addMediaQueriesPlugin.js"
|
9
|
+
import addPseudoClassesPlugin from "./post-css-plugins/addPseudoClassesPlugin.js"
|
10
|
+
import generateDocumentationPlugin from "./post-css-plugins/generateDocumentationPlugin.js"
|
11
|
+
|
12
|
+
import mediaQueryConfigParser from "./mediaQueryConfigParser.js"
|
13
|
+
import pseudoClassConfigParser from "./pseudoClassConfigParser.js"
|
14
|
+
|
15
|
+
import docGenerator from "./docGenerator.js"
|
16
|
+
import parseCLI from "./cli.js"
|
17
|
+
|
18
|
+
const generateCSS = ({
|
19
|
+
input,
|
20
|
+
output,
|
21
|
+
mediaQueryConfig,
|
22
|
+
pseudoClassConfig,
|
23
|
+
docsDir,
|
24
|
+
docsTemplateSourceDir,
|
25
|
+
pathToBrutCSSRoot,
|
26
|
+
debug,
|
27
|
+
}) => {
|
28
|
+
|
29
|
+
Logger.instance = new Logger("build.js")
|
30
|
+
if (debug.debug) {
|
31
|
+
Logger.instance.level = "debug"
|
32
|
+
}
|
33
|
+
|
34
|
+
const inputCSS = fs.readFileSync(input.filename, 'utf8')
|
35
|
+
const mediaQueries = mediaQueryConfigParser(mediaQueryConfig.filename)
|
36
|
+
const pseudoClasses = pseudoClassConfigParser(pseudoClassConfig.filename)
|
37
|
+
|
38
|
+
let error = false
|
39
|
+
mediaQueries.forEach( (mediaQuery) => {
|
40
|
+
if (mediaQuery.isError()) {
|
41
|
+
error = true
|
42
|
+
Logger.error(`Error with media query '${mediaQuery.rawQuery}': ${mediaQuery.error}`)
|
43
|
+
}
|
44
|
+
})
|
45
|
+
pseudoClasses.forEach( (pseudoClass) => {
|
46
|
+
if (pseudoClass.isError()) {
|
47
|
+
error = true
|
48
|
+
Logger.error(`Error with pseudo class '${pseudoClass.rule}': ${pseudoClass.error}`)
|
49
|
+
}
|
50
|
+
})
|
51
|
+
if (error) {
|
52
|
+
process.exit(1)
|
53
|
+
}
|
54
|
+
|
55
|
+
const postCSSPlugins = [
|
56
|
+
postcssImport(),
|
57
|
+
generateRootCustomPropertiesPlugin(),
|
58
|
+
]
|
59
|
+
|
60
|
+
|
61
|
+
let parsedDocumentation = null
|
62
|
+
if (docsDir.dirname) {
|
63
|
+
if (!docsTemplateSourceDir.dirname) {
|
64
|
+
Logger.error("You must provide docs-template-source-dir when supplying docs-dir")
|
65
|
+
process.exit(1)
|
66
|
+
}
|
67
|
+
parsedDocumentation = {}
|
68
|
+
postCSSPlugins.push(generateDocumentationPlugin(parsedDocumentation))
|
69
|
+
}
|
70
|
+
postCSSPlugins.push(addPseudoClassesPlugin(pseudoClasses))
|
71
|
+
postCSSPlugins.push(addMediaQueriesPlugin(mediaQueries))
|
72
|
+
|
73
|
+
|
74
|
+
postcss(postCSSPlugins).process(
|
75
|
+
inputCSS, { from: input.filename }
|
76
|
+
).then( result => {
|
77
|
+
const dirname = path.dirname(output.filename)
|
78
|
+
if (!fs.existsSync(dirname)) {
|
79
|
+
fs.mkdirSync(dirname, { recursive: true })
|
80
|
+
}
|
81
|
+
fs.writeFileSync(output.filename,result.css,"utf8")
|
82
|
+
if (docsDir.dirname) {
|
83
|
+
fs.mkdirSync(docsDir.dirname, { recursive: true })
|
84
|
+
fs.readdirSync(docsDir.dirname).forEach( (relativePath) => {
|
85
|
+
const fullPath = path.join(docsDir.dirname,relativePath)
|
86
|
+
fs.rmSync(fullPath,{recursive: true})
|
87
|
+
})
|
88
|
+
docGenerator(docsDir.dirname, docsTemplateSourceDir.dirname, parsedDocumentation, pathToBrutCSSRoot.uri)
|
89
|
+
Logger.log(`Docs generated in ${docsDir.dirname}`)
|
90
|
+
}
|
91
|
+
Logger.log(`CSS saved to ${output.filename}`)
|
92
|
+
}).catch( (error) => {
|
93
|
+
Logger.log("Error: %o", error)
|
94
|
+
process.exit(1)
|
95
|
+
})
|
96
|
+
}
|
97
|
+
|
98
|
+
const parseResult = parseCLI(process.argv)
|
99
|
+
if (parseResult.shouldExit()) {
|
100
|
+
if (parseResult.isError()) {
|
101
|
+
if (parseResult.errorMessage) {
|
102
|
+
Logger.error(`Error: ${parseResult.errorMessage}`)
|
103
|
+
}
|
104
|
+
process.exit(1)
|
105
|
+
}
|
106
|
+
else {
|
107
|
+
process.exit(0)
|
108
|
+
}
|
109
|
+
}
|
110
|
+
generateCSS(parseResult.args)
|
111
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import CLIArgError from "./CLIArgError.js"
|
2
|
+
import ParsedArg from "./ParsedArg.js"
|
3
|
+
|
4
|
+
export default class Debug extends ParsedArg {
|
5
|
+
static field = "debug"
|
6
|
+
static description = "Show lots of output"
|
7
|
+
static shortField = "g"
|
8
|
+
|
9
|
+
static toParseArgsOption() {
|
10
|
+
return [
|
11
|
+
this.longField,
|
12
|
+
{
|
13
|
+
type: "boolean",
|
14
|
+
multiple: false,
|
15
|
+
short: "g",
|
16
|
+
}
|
17
|
+
]
|
18
|
+
}
|
19
|
+
|
20
|
+
static parse(values) {
|
21
|
+
return new Debug(values[this.field])
|
22
|
+
}
|
23
|
+
constructor(debug) {
|
24
|
+
super()
|
25
|
+
this.debug = !!debug
|
26
|
+
}
|
27
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import ParsedArg from "./ParsedArg.js"
|
2
|
+
|
3
|
+
export default class DocsDir extends ParsedArg {
|
4
|
+
static field = "docsDir"
|
5
|
+
static description = "path to generate documentation"
|
6
|
+
static shortField = "d"
|
7
|
+
|
8
|
+
static parse(values) {
|
9
|
+
const dirname = values[this.longField]
|
10
|
+
return new this(dirname)
|
11
|
+
}
|
12
|
+
constructor(dirname) {
|
13
|
+
super()
|
14
|
+
this.dirname = dirname
|
15
|
+
}
|
16
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import ParsedArg from "./ParsedArg.js"
|
2
|
+
|
3
|
+
export default class DocsTemplateSourceDir extends ParsedArg {
|
4
|
+
static field = "docsTemplateSourceDir"
|
5
|
+
static description = "path where doc templates live"
|
6
|
+
static shortField = "t"
|
7
|
+
|
8
|
+
static parse(values) {
|
9
|
+
const dirname = values[this.longField]
|
10
|
+
return new this(dirname)
|
11
|
+
}
|
12
|
+
constructor(dirname) {
|
13
|
+
super()
|
14
|
+
this.dirname = dirname
|
15
|
+
}
|
16
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import fs from "node:fs"
|
2
|
+
import CLIArgError from "./CLIArgError.js"
|
3
|
+
import ParsedArg from "./ParsedArg.js"
|
4
|
+
|
5
|
+
export default class InputFile extends ParsedArg {
|
6
|
+
static field = "input"
|
7
|
+
static description = "Input .css to process"
|
8
|
+
static shortField = "i"
|
9
|
+
|
10
|
+
static parse(values) {
|
11
|
+
const filename = values[this.longField]
|
12
|
+
if (filename) {
|
13
|
+
if (fs.existsSync(filename)) {
|
14
|
+
return new this(filename)
|
15
|
+
}
|
16
|
+
else {
|
17
|
+
return new CLIArgError(this.longField,`File '${filename}' does not exist`)
|
18
|
+
}
|
19
|
+
}
|
20
|
+
else {
|
21
|
+
return this._handleNoValue()
|
22
|
+
}
|
23
|
+
}
|
24
|
+
constructor(filename) {
|
25
|
+
super()
|
26
|
+
this.filename = filename
|
27
|
+
}
|
28
|
+
static _handleNoValue() {
|
29
|
+
return new CLIArgError(this.field,"is required")
|
30
|
+
}
|
31
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import InputFile from "./InputFile.js"
|
2
|
+
|
3
|
+
export default class MediaQueryConfigFile extends InputFile {
|
4
|
+
static field = "mediaQueryConfig"
|
5
|
+
static description = "Specialized .css describing the media queries to support in the output"
|
6
|
+
static shortField = "m"
|
7
|
+
static _handleNoValue() {
|
8
|
+
return new MediaQueryConfigFile()
|
9
|
+
}
|
10
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import CLIArgError from "./CLIArgError.js"
|
2
|
+
import ParsedArg from "./ParsedArg.js"
|
3
|
+
|
4
|
+
export default class OutputFile extends ParsedArg {
|
5
|
+
static field = "output"
|
6
|
+
static description = "Output .css (this is what your app will use)"
|
7
|
+
static shortField = "o"
|
8
|
+
|
9
|
+
static parse(values) {
|
10
|
+
const filename = values[this.field]
|
11
|
+
if (filename) {
|
12
|
+
return new OutputFile(filename)
|
13
|
+
}
|
14
|
+
else {
|
15
|
+
return new CLIArgError(this.field,"is required")
|
16
|
+
}
|
17
|
+
}
|
18
|
+
constructor(filename) {
|
19
|
+
super()
|
20
|
+
this.filename = filename
|
21
|
+
}
|
22
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
export default class ParsedArg {
|
2
|
+
hasError() { return false }
|
3
|
+
static isArray() { return false }
|
4
|
+
static toParseArgsOption() {
|
5
|
+
return [
|
6
|
+
this.longField,
|
7
|
+
{
|
8
|
+
type: "string",
|
9
|
+
multiple: this.isArray(),
|
10
|
+
short: this.shortField,
|
11
|
+
}
|
12
|
+
]
|
13
|
+
}
|
14
|
+
static get longField() {
|
15
|
+
return this.field.replace(/([A-Z])/g, '-$1').toLowerCase()
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import ParsedArg from "./ParsedArg.js"
|
2
|
+
|
3
|
+
export default class PathToBrutCSSRoot extends ParsedArg {
|
4
|
+
static field = "pathToBrutCSSRoot"
|
5
|
+
static description = "Relative URI to where BrutCSS docs on brutrb.com will be"
|
6
|
+
static shortField = "r"
|
7
|
+
|
8
|
+
static parse(values) {
|
9
|
+
const uri = values[this.longField]
|
10
|
+
return new this(uri)
|
11
|
+
}
|
12
|
+
constructor(uri) {
|
13
|
+
super()
|
14
|
+
this.uri = uri
|
15
|
+
}
|
16
|
+
static get longField() {
|
17
|
+
return "path-to-brut-css-root"
|
18
|
+
}
|
19
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import InputFile from "./InputFile.js"
|
2
|
+
|
3
|
+
export default class PseudoClassConfigFile extends InputFile {
|
4
|
+
static field = "pseudoClassConfig"
|
5
|
+
static description = "Specialized .css describing the pseudo classes to support in the output"
|
6
|
+
static shortField = "p"
|
7
|
+
|
8
|
+
static _handleNoValue() {
|
9
|
+
return new PseudoClassConfigFile()
|
10
|
+
}
|
11
|
+
}
|
@@ -0,0 +1,108 @@
|
|
1
|
+
import { parseArgs } from "node:util"
|
2
|
+
import InputFile from "./cli/InputFile.js"
|
3
|
+
import MediaQueryConfigFile from "./cli/MediaQueryConfigFile.js"
|
4
|
+
import PseudoClassConfigFile from "./cli/PseudoClassConfigFile.js"
|
5
|
+
import OutputFile from "./cli/OutputFile.js"
|
6
|
+
import DocsDir from "./cli/DocsDir.js"
|
7
|
+
import DocsTemplateSourceDir from "./cli/DocsTemplateSourceDir.js"
|
8
|
+
import PathToBrutCSSRoot from "./cli/PathToBrutCSSRoot.js"
|
9
|
+
import Debug from "./cli/Debug.js"
|
10
|
+
|
11
|
+
const cliArgs = [
|
12
|
+
InputFile,
|
13
|
+
MediaQueryConfigFile,
|
14
|
+
PseudoClassConfigFile,
|
15
|
+
OutputFile,
|
16
|
+
DocsDir,
|
17
|
+
DocsTemplateSourceDir,
|
18
|
+
PathToBrutCSSRoot,
|
19
|
+
Debug,
|
20
|
+
]
|
21
|
+
|
22
|
+
const parseArgsOptions = Object.fromEntries(cliArgs.map( (argClass) => argClass.toParseArgsOption() ))
|
23
|
+
|
24
|
+
const showHelp = () => {
|
25
|
+
console.log("usage: build.js [options]")
|
26
|
+
console.log()
|
27
|
+
console.log("OPTIONS")
|
28
|
+
console.log()
|
29
|
+
let maxFieldLength = 0
|
30
|
+
cliArgs.forEach( (argClass) => {
|
31
|
+
maxFieldLength = Math.max(maxFieldLength,argClass.longField.length)
|
32
|
+
})
|
33
|
+
|
34
|
+
cliArgs.forEach( (argClass) => {
|
35
|
+
console.log(" -%s/%s - %s",argClass.shortField,`--${argClass.longField}`.padEnd(maxFieldLength + 2),argClass.description)
|
36
|
+
if (argClass.isArray()) {
|
37
|
+
console.log(" [use multiple times for mulitple values]")
|
38
|
+
}
|
39
|
+
})
|
40
|
+
}
|
41
|
+
|
42
|
+
class ParseResult {
|
43
|
+
constructor(parsedArgs) {
|
44
|
+
this.args = parsedArgs
|
45
|
+
}
|
46
|
+
shouldExit() { return false }
|
47
|
+
isError() { return false }
|
48
|
+
}
|
49
|
+
|
50
|
+
class ExitParseResult extends ParseResult {
|
51
|
+
constructor() {
|
52
|
+
super({})
|
53
|
+
}
|
54
|
+
shouldExit() { return true }
|
55
|
+
isError() { return false }
|
56
|
+
}
|
57
|
+
class ErrorParseResult extends ExitParseResult {
|
58
|
+
constructor(errorMessage) {
|
59
|
+
super()
|
60
|
+
this.errorMessage = errorMessage
|
61
|
+
}
|
62
|
+
isError() { return true }
|
63
|
+
}
|
64
|
+
|
65
|
+
const parseCLI = (argv) => {
|
66
|
+
const firstArg = argv[2]
|
67
|
+
|
68
|
+
if ( !firstArg ||
|
69
|
+
firstArg == "--help" ||
|
70
|
+
firstArg == "-h" ||
|
71
|
+
firstArg == "-help" ||
|
72
|
+
firstArg == "help" ) {
|
73
|
+
|
74
|
+
showHelp()
|
75
|
+
return new ExitParseResult()
|
76
|
+
}
|
77
|
+
|
78
|
+
try {
|
79
|
+
const args = process.argv.slice(2)
|
80
|
+
const {
|
81
|
+
values,
|
82
|
+
positionals
|
83
|
+
} = parseArgs({
|
84
|
+
args: args,
|
85
|
+
options: parseArgsOptions,
|
86
|
+
strict: true,
|
87
|
+
})
|
88
|
+
|
89
|
+
const parsedValues = cliArgs.map( (klass) => klass.parse(values) )
|
90
|
+
|
91
|
+
const errors = parsedValues.filter( (pv) => pv.hasError() )
|
92
|
+
|
93
|
+
if (errors.length > 0) {
|
94
|
+
console.log("%d %s in command-line arguments:",errors.length,errors.length == 1 ? "error" : "errors")
|
95
|
+
console.log()
|
96
|
+
errors.forEach( (error) => {
|
97
|
+
console.log(" --%s - %s",error.field.padEnd(18),error.errorMessage)
|
98
|
+
})
|
99
|
+
return new ErrorParseResult()
|
100
|
+
}
|
101
|
+
|
102
|
+
return new ParseResult(Object.fromEntries(parsedValues.map( (pv) => [ pv.constructor.field,pv] )))
|
103
|
+
}
|
104
|
+
catch (error) {
|
105
|
+
return new ErrorParseResult(error.message)
|
106
|
+
}
|
107
|
+
}
|
108
|
+
export default parseCLI
|