@empline/preflight 1.1.11 → 1.1.13
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.
- package/dist/checks/consolidated/auth-storage-state.d.ts +3 -0
- package/dist/checks/consolidated/auth-storage-state.d.ts.map +1 -0
- package/dist/checks/consolidated/auth-storage-state.js +146 -0
- package/dist/checks/consolidated/auth-storage-state.js.map +1 -0
- package/dist/checks/consolidated/business.d.ts +50 -0
- package/dist/checks/consolidated/business.d.ts.map +1 -0
- package/dist/checks/consolidated/business.js +252 -0
- package/dist/checks/consolidated/business.js.map +1 -0
- package/dist/checks/consolidated/caching-strategy.d.ts +104 -0
- package/dist/checks/consolidated/caching-strategy.d.ts.map +1 -0
- package/dist/checks/consolidated/caching-strategy.js +725 -0
- package/dist/checks/consolidated/caching-strategy.js.map +1 -0
- package/dist/checks/consolidated/code-quality.d.ts +83 -0
- package/dist/checks/consolidated/code-quality.d.ts.map +1 -0
- package/dist/checks/consolidated/code-quality.js +445 -0
- package/dist/checks/consolidated/code-quality.js.map +1 -0
- package/dist/checks/consolidated/console-statements.d.ts +32 -0
- package/dist/checks/consolidated/console-statements.d.ts.map +1 -0
- package/dist/checks/consolidated/console-statements.js +304 -0
- package/dist/checks/consolidated/console-statements.js.map +1 -0
- package/dist/checks/consolidated/css-advanced-validation.d.ts +24 -0
- package/dist/checks/consolidated/css-advanced-validation.d.ts.map +1 -0
- package/dist/checks/consolidated/css-advanced-validation.js +415 -0
- package/dist/checks/consolidated/css-advanced-validation.js.map +1 -0
- package/dist/checks/consolidated/css-organization.d.ts +14 -0
- package/dist/checks/consolidated/css-organization.d.ts.map +1 -0
- package/dist/checks/consolidated/css-organization.js +432 -0
- package/dist/checks/consolidated/css-organization.js.map +1 -0
- package/dist/checks/consolidated/css-runtime-validation.d.ts +22 -0
- package/dist/checks/consolidated/css-runtime-validation.d.ts.map +1 -0
- package/dist/checks/consolidated/css-runtime-validation.js +330 -0
- package/dist/checks/consolidated/css-runtime-validation.js.map +1 -0
- package/dist/checks/consolidated/css-variable-validation.d.ts +17 -0
- package/dist/checks/consolidated/css-variable-validation.d.ts.map +1 -0
- package/dist/checks/consolidated/css-variable-validation.js +412 -0
- package/dist/checks/consolidated/css-variable-validation.js.map +1 -0
- package/dist/checks/consolidated/dark-mode-consistency.d.ts +23 -0
- package/dist/checks/consolidated/dark-mode-consistency.d.ts.map +1 -0
- package/dist/checks/consolidated/dark-mode-consistency.js +291 -0
- package/dist/checks/consolidated/dark-mode-consistency.js.map +1 -0
- package/dist/checks/consolidated/database.d.ts +95 -0
- package/dist/checks/consolidated/database.d.ts.map +1 -0
- package/dist/checks/consolidated/database.js +427 -0
- package/dist/checks/consolidated/database.js.map +1 -0
- package/dist/checks/consolidated/e2e-checks.d.ts +52 -0
- package/dist/checks/consolidated/e2e-checks.d.ts.map +1 -0
- package/dist/checks/consolidated/e2e-checks.js +157 -0
- package/dist/checks/consolidated/e2e-checks.js.map +1 -0
- package/dist/checks/consolidated/e2e-regression-coverage.d.ts +14 -0
- package/dist/checks/consolidated/e2e-regression-coverage.d.ts.map +1 -0
- package/dist/checks/consolidated/e2e-regression-coverage.js +151 -0
- package/dist/checks/consolidated/e2e-regression-coverage.js.map +1 -0
- package/dist/checks/consolidated/e2e-validation.d.ts +137 -0
- package/dist/checks/consolidated/e2e-validation.d.ts.map +1 -0
- package/dist/checks/consolidated/e2e-validation.js +1001 -0
- package/dist/checks/consolidated/e2e-validation.js.map +1 -0
- package/dist/checks/consolidated/enterprise-baseline.d.ts +9 -0
- package/dist/checks/consolidated/enterprise-baseline.d.ts.map +1 -0
- package/dist/checks/consolidated/enterprise-baseline.js +277 -0
- package/dist/checks/consolidated/enterprise-baseline.js.map +1 -0
- package/dist/checks/consolidated/generate-pageload-config.d.ts +6 -0
- package/dist/checks/consolidated/generate-pageload-config.d.ts.map +1 -0
- package/dist/checks/consolidated/generate-pageload-config.js +161 -0
- package/dist/checks/consolidated/generate-pageload-config.js.map +1 -0
- package/dist/checks/consolidated/hardened-checks.d.ts +276 -0
- package/dist/checks/consolidated/hardened-checks.d.ts.map +1 -0
- package/dist/checks/consolidated/hardened-checks.js +3056 -0
- package/dist/checks/consolidated/hardened-checks.js.map +1 -0
- package/dist/checks/consolidated/homepage-ux.d.ts +12 -0
- package/dist/checks/consolidated/homepage-ux.d.ts.map +1 -0
- package/dist/checks/consolidated/homepage-ux.js +242 -0
- package/dist/checks/consolidated/homepage-ux.js.map +1 -0
- package/dist/checks/consolidated/images.d.ts +76 -0
- package/dist/checks/consolidated/images.d.ts.map +1 -0
- package/dist/checks/consolidated/images.js +311 -0
- package/dist/checks/consolidated/images.js.map +1 -0
- package/dist/checks/consolidated/import-cycles.d.ts +63 -0
- package/dist/checks/consolidated/import-cycles.d.ts.map +1 -0
- package/dist/checks/consolidated/import-cycles.js +291 -0
- package/dist/checks/consolidated/import-cycles.js.map +1 -0
- package/dist/checks/consolidated/imports.d.ts +112 -0
- package/dist/checks/consolidated/imports.d.ts.map +1 -0
- package/dist/checks/consolidated/imports.js +977 -0
- package/dist/checks/consolidated/imports.js.map +1 -0
- package/dist/checks/consolidated/inline-style-conflicts.d.ts +21 -0
- package/dist/checks/consolidated/inline-style-conflicts.d.ts.map +1 -0
- package/dist/checks/consolidated/inline-style-conflicts.js +300 -0
- package/dist/checks/consolidated/inline-style-conflicts.js.map +1 -0
- package/dist/checks/consolidated/lib-organization.d.ts +12 -0
- package/dist/checks/consolidated/lib-organization.d.ts.map +1 -0
- package/dist/checks/consolidated/lib-organization.js +419 -0
- package/dist/checks/consolidated/lib-organization.js.map +1 -0
- package/dist/checks/consolidated/n-plus-one.d.ts +63 -0
- package/dist/checks/consolidated/n-plus-one.d.ts.map +1 -0
- package/dist/checks/consolidated/n-plus-one.js +331 -0
- package/dist/checks/consolidated/n-plus-one.js.map +1 -0
- package/dist/checks/consolidated/nextjs.d.ts +51 -0
- package/dist/checks/consolidated/nextjs.d.ts.map +1 -0
- package/dist/checks/consolidated/nextjs.js +205 -0
- package/dist/checks/consolidated/nextjs.js.map +1 -0
- package/dist/checks/consolidated/organization.d.ts +54 -0
- package/dist/checks/consolidated/organization.d.ts.map +1 -0
- package/dist/checks/consolidated/organization.js +158 -0
- package/dist/checks/consolidated/organization.js.map +1 -0
- package/dist/checks/consolidated/pageload.d.ts +12 -0
- package/dist/checks/consolidated/pageload.d.ts.map +1 -0
- package/dist/checks/consolidated/pageload.js +138 -0
- package/dist/checks/consolidated/pageload.js.map +1 -0
- package/dist/checks/consolidated/performance.d.ts +112 -0
- package/dist/checks/consolidated/performance.d.ts.map +1 -0
- package/dist/checks/consolidated/performance.js +1546 -0
- package/dist/checks/consolidated/performance.js.map +1 -0
- package/dist/checks/consolidated/quality.d.ts +52 -0
- package/dist/checks/consolidated/quality.d.ts.map +1 -0
- package/dist/checks/consolidated/quality.js +253 -0
- package/dist/checks/consolidated/quality.js.map +1 -0
- package/dist/checks/consolidated/react.d.ts +48 -0
- package/dist/checks/consolidated/react.d.ts.map +1 -0
- package/dist/checks/consolidated/react.js +203 -0
- package/dist/checks/consolidated/react.js.map +1 -0
- package/dist/checks/consolidated/regression-hygiene.d.ts +17 -0
- package/dist/checks/consolidated/regression-hygiene.d.ts.map +1 -0
- package/dist/checks/consolidated/regression-hygiene.js +242 -0
- package/dist/checks/consolidated/regression-hygiene.js.map +1 -0
- package/dist/checks/consolidated/regression.d.ts +20 -0
- package/dist/checks/consolidated/regression.d.ts.map +1 -0
- package/dist/checks/consolidated/regression.js +121 -0
- package/dist/checks/consolidated/regression.js.map +1 -0
- package/dist/checks/consolidated/runtime.d.ts +53 -0
- package/dist/checks/consolidated/runtime.d.ts.map +1 -0
- package/dist/checks/consolidated/runtime.js +160 -0
- package/dist/checks/consolidated/runtime.js.map +1 -0
- package/dist/checks/consolidated/script-performance.d.ts +17 -0
- package/dist/checks/consolidated/script-performance.d.ts.map +1 -0
- package/dist/checks/consolidated/script-performance.js +137 -0
- package/dist/checks/consolidated/script-performance.js.map +1 -0
- package/dist/checks/consolidated/security.d.ts +78 -0
- package/dist/checks/consolidated/security.d.ts.map +1 -0
- package/dist/checks/consolidated/security.js +404 -0
- package/dist/checks/consolidated/security.js.map +1 -0
- package/dist/checks/consolidated/seo.d.ts +31 -0
- package/dist/checks/consolidated/seo.d.ts.map +1 -0
- package/dist/checks/consolidated/seo.js +1438 -0
- package/dist/checks/consolidated/seo.js.map +1 -0
- package/dist/checks/consolidated/sx-prop-deprecation.d.ts +22 -0
- package/dist/checks/consolidated/sx-prop-deprecation.d.ts.map +1 -0
- package/dist/checks/consolidated/sx-prop-deprecation.js +280 -0
- package/dist/checks/consolidated/sx-prop-deprecation.js.map +1 -0
- package/dist/checks/consolidated/tailwind-class-validation.d.ts +25 -0
- package/dist/checks/consolidated/tailwind-class-validation.d.ts.map +1 -0
- package/dist/checks/consolidated/tailwind-class-validation.js +533 -0
- package/dist/checks/consolidated/tailwind-class-validation.js.map +1 -0
- package/dist/checks/consolidated/testing.d.ts +54 -0
- package/dist/checks/consolidated/testing.d.ts.map +1 -0
- package/dist/checks/consolidated/testing.js +163 -0
- package/dist/checks/consolidated/testing.js.map +1 -0
- package/dist/checks/consolidated/typescript.d.ts +3 -0
- package/dist/checks/consolidated/typescript.d.ts.map +1 -0
- package/dist/checks/consolidated/typescript.js +31 -0
- package/dist/checks/consolidated/typescript.js.map +1 -0
- package/dist/checks/consolidated/ui-accessibility-advanced.d.ts +104 -0
- package/dist/checks/consolidated/ui-accessibility-advanced.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-accessibility-advanced.js +689 -0
- package/dist/checks/consolidated/ui-accessibility-advanced.js.map +1 -0
- package/dist/checks/consolidated/ui-accessibility.d.ts +121 -0
- package/dist/checks/consolidated/ui-accessibility.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-accessibility.js +776 -0
- package/dist/checks/consolidated/ui-accessibility.js.map +1 -0
- package/dist/checks/consolidated/ui-advanced-spacing.d.ts +142 -0
- package/dist/checks/consolidated/ui-advanced-spacing.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-advanced-spacing.js +1220 -0
- package/dist/checks/consolidated/ui-advanced-spacing.js.map +1 -0
- package/dist/checks/consolidated/ui-animation-duration.d.ts +108 -0
- package/dist/checks/consolidated/ui-animation-duration.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-animation-duration.js +531 -0
- package/dist/checks/consolidated/ui-animation-duration.js.map +1 -0
- package/dist/checks/consolidated/ui-border-radius.d.ts +90 -0
- package/dist/checks/consolidated/ui-border-radius.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-border-radius.js +519 -0
- package/dist/checks/consolidated/ui-border-radius.js.map +1 -0
- package/dist/checks/consolidated/ui-buttons.d.ts +32 -0
- package/dist/checks/consolidated/ui-buttons.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-buttons.js +481 -0
- package/dist/checks/consolidated/ui-buttons.js.map +1 -0
- package/dist/checks/consolidated/ui-cards.d.ts +29 -0
- package/dist/checks/consolidated/ui-cards.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-cards.js +504 -0
- package/dist/checks/consolidated/ui-cards.js.map +1 -0
- package/dist/checks/consolidated/ui-checks.d.ts +48 -0
- package/dist/checks/consolidated/ui-checks.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-checks.js +264 -0
- package/dist/checks/consolidated/ui-checks.js.map +1 -0
- package/dist/checks/consolidated/ui-cleanup.d.ts +81 -0
- package/dist/checks/consolidated/ui-cleanup.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-cleanup.js +650 -0
- package/dist/checks/consolidated/ui-cleanup.js.map +1 -0
- package/dist/checks/consolidated/ui-components.d.ts +255 -0
- package/dist/checks/consolidated/ui-components.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-components.js +2008 -0
- package/dist/checks/consolidated/ui-components.js.map +1 -0
- package/dist/checks/consolidated/ui-consistency-advanced.d.ts +130 -0
- package/dist/checks/consolidated/ui-consistency-advanced.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-consistency-advanced.js +982 -0
- package/dist/checks/consolidated/ui-consistency-advanced.js.map +1 -0
- package/dist/checks/consolidated/ui-consistency-comprehensive.d.ts +30 -0
- package/dist/checks/consolidated/ui-consistency-comprehensive.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-consistency-comprehensive.js +1018 -0
- package/dist/checks/consolidated/ui-consistency-comprehensive.js.map +1 -0
- package/dist/checks/consolidated/ui-consistency-extended.d.ts +26 -0
- package/dist/checks/consolidated/ui-consistency-extended.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-consistency-extended.js +606 -0
- package/dist/checks/consolidated/ui-consistency-extended.js.map +1 -0
- package/dist/checks/consolidated/ui-data-display.d.ts +103 -0
- package/dist/checks/consolidated/ui-data-display.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-data-display.js +740 -0
- package/dist/checks/consolidated/ui-data-display.js.map +1 -0
- package/dist/checks/consolidated/ui-deprecated.d.ts +22 -0
- package/dist/checks/consolidated/ui-deprecated.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-deprecated.js +336 -0
- package/dist/checks/consolidated/ui-deprecated.js.map +1 -0
- package/dist/checks/consolidated/ui-empty-null-states.d.ts +90 -0
- package/dist/checks/consolidated/ui-empty-null-states.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-empty-null-states.js +511 -0
- package/dist/checks/consolidated/ui-empty-null-states.js.map +1 -0
- package/dist/checks/consolidated/ui-error-states.d.ts +99 -0
- package/dist/checks/consolidated/ui-error-states.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-error-states.js +694 -0
- package/dist/checks/consolidated/ui-error-states.js.map +1 -0
- package/dist/checks/consolidated/ui-feedback-confirmations.d.ts +90 -0
- package/dist/checks/consolidated/ui-feedback-confirmations.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-feedback-confirmations.js +596 -0
- package/dist/checks/consolidated/ui-feedback-confirmations.js.map +1 -0
- package/dist/checks/consolidated/ui-forms.d.ts +32 -0
- package/dist/checks/consolidated/ui-forms.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-forms.js +568 -0
- package/dist/checks/consolidated/ui-forms.js.map +1 -0
- package/dist/checks/consolidated/ui-gradient-shadow.d.ts +90 -0
- package/dist/checks/consolidated/ui-gradient-shadow.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-gradient-shadow.js +568 -0
- package/dist/checks/consolidated/ui-gradient-shadow.js.map +1 -0
- package/dist/checks/consolidated/ui-grid-responsive.d.ts +27 -0
- package/dist/checks/consolidated/ui-grid-responsive.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-grid-responsive.js +441 -0
- package/dist/checks/consolidated/ui-grid-responsive.js.map +1 -0
- package/dist/checks/consolidated/ui-icon-size-tokens.d.ts +104 -0
- package/dist/checks/consolidated/ui-icon-size-tokens.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-icon-size-tokens.js +514 -0
- package/dist/checks/consolidated/ui-icon-size-tokens.js.map +1 -0
- package/dist/checks/consolidated/ui-iconography.d.ts +90 -0
- package/dist/checks/consolidated/ui-iconography.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-iconography.js +565 -0
- package/dist/checks/consolidated/ui-iconography.js.map +1 -0
- package/dist/checks/consolidated/ui-interactive-states.d.ts +240 -0
- package/dist/checks/consolidated/ui-interactive-states.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-interactive-states.js +2474 -0
- package/dist/checks/consolidated/ui-interactive-states.js.map +1 -0
- package/dist/checks/consolidated/ui-layout.d.ts +256 -0
- package/dist/checks/consolidated/ui-layout.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-layout.js +1371 -0
- package/dist/checks/consolidated/ui-layout.js.map +1 -0
- package/dist/checks/consolidated/ui-loading-skeletons.d.ts +11 -0
- package/dist/checks/consolidated/ui-loading-skeletons.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-loading-skeletons.js +145 -0
- package/dist/checks/consolidated/ui-loading-skeletons.js.map +1 -0
- package/dist/checks/consolidated/ui-loading-state-skeletons.d.ts +9 -0
- package/dist/checks/consolidated/ui-loading-state-skeletons.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-loading-state-skeletons.js +125 -0
- package/dist/checks/consolidated/ui-loading-state-skeletons.js.map +1 -0
- package/dist/checks/consolidated/ui-media.d.ts +74 -0
- package/dist/checks/consolidated/ui-media.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-media.js +408 -0
- package/dist/checks/consolidated/ui-media.js.map +1 -0
- package/dist/checks/consolidated/ui-micro-interactions.d.ts +107 -0
- package/dist/checks/consolidated/ui-micro-interactions.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-micro-interactions.js +825 -0
- package/dist/checks/consolidated/ui-micro-interactions.js.map +1 -0
- package/dist/checks/consolidated/ui-microcopy-consistency.d.ts +114 -0
- package/dist/checks/consolidated/ui-microcopy-consistency.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-microcopy-consistency.js +566 -0
- package/dist/checks/consolidated/ui-microcopy-consistency.js.map +1 -0
- package/dist/checks/consolidated/ui-mobile-ux.d.ts +251 -0
- package/dist/checks/consolidated/ui-mobile-ux.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-mobile-ux.js +2212 -0
- package/dist/checks/consolidated/ui-mobile-ux.js.map +1 -0
- package/dist/checks/consolidated/ui-motion-accessibility.d.ts +93 -0
- package/dist/checks/consolidated/ui-motion-accessibility.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-motion-accessibility.js +450 -0
- package/dist/checks/consolidated/ui-motion-accessibility.js.map +1 -0
- package/dist/checks/consolidated/ui-navigation.d.ts +85 -0
- package/dist/checks/consolidated/ui-navigation.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-navigation.js +673 -0
- package/dist/checks/consolidated/ui-navigation.js.map +1 -0
- package/dist/checks/consolidated/ui-patterns.d.ts +174 -0
- package/dist/checks/consolidated/ui-patterns.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-patterns.js +1532 -0
- package/dist/checks/consolidated/ui-patterns.js.map +1 -0
- package/dist/checks/consolidated/ui-responsive.d.ts +89 -0
- package/dist/checks/consolidated/ui-responsive.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-responsive.js +588 -0
- package/dist/checks/consolidated/ui-responsive.js.map +1 -0
- package/dist/checks/consolidated/ui-spacing-standards.d.ts +43 -0
- package/dist/checks/consolidated/ui-spacing-standards.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-spacing-standards.js +874 -0
- package/dist/checks/consolidated/ui-spacing-standards.js.map +1 -0
- package/dist/checks/consolidated/ui-spacing.d.ts +751 -0
- package/dist/checks/consolidated/ui-spacing.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-spacing.js +4996 -0
- package/dist/checks/consolidated/ui-spacing.js.map +1 -0
- package/dist/checks/consolidated/ui-standards-auto-fixer.d.ts +70 -0
- package/dist/checks/consolidated/ui-standards-auto-fixer.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-standards-auto-fixer.js +429 -0
- package/dist/checks/consolidated/ui-standards-auto-fixer.js.map +1 -0
- package/dist/checks/consolidated/ui-standards-enforcement.d.ts +100 -0
- package/dist/checks/consolidated/ui-standards-enforcement.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-standards-enforcement.js +935 -0
- package/dist/checks/consolidated/ui-standards-enforcement.js.map +1 -0
- package/dist/checks/consolidated/ui-state-consistency.d.ts +90 -0
- package/dist/checks/consolidated/ui-state-consistency.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-state-consistency.js +659 -0
- package/dist/checks/consolidated/ui-state-consistency.js.map +1 -0
- package/dist/checks/consolidated/ui-style-validation.d.ts +74 -0
- package/dist/checks/consolidated/ui-style-validation.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-style-validation.js +403 -0
- package/dist/checks/consolidated/ui-style-validation.js.map +1 -0
- package/dist/checks/consolidated/ui-tokens.d.ts +110 -0
- package/dist/checks/consolidated/ui-tokens.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-tokens.js +990 -0
- package/dist/checks/consolidated/ui-tokens.js.map +1 -0
- package/dist/checks/consolidated/ui-typography.d.ts +77 -0
- package/dist/checks/consolidated/ui-typography.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-typography.js +416 -0
- package/dist/checks/consolidated/ui-typography.js.map +1 -0
- package/dist/checks/consolidated/ui-visual-hierarchy.d.ts +90 -0
- package/dist/checks/consolidated/ui-visual-hierarchy.d.ts.map +1 -0
- package/dist/checks/consolidated/ui-visual-hierarchy.js +562 -0
- package/dist/checks/consolidated/ui-visual-hierarchy.js.map +1 -0
- package/dist/checks/consolidated/woocommerce.d.ts +50 -0
- package/dist/checks/consolidated/woocommerce.d.ts.map +1 -0
- package/dist/checks/consolidated/woocommerce.js +198 -0
- package/dist/checks/consolidated/woocommerce.js.map +1 -0
- package/dist/checks/core/api-route-protection.d.ts +2 -0
- package/dist/checks/core/api-route-protection.d.ts.map +1 -0
- package/dist/checks/core/api-route-protection.js +101 -0
- package/dist/checks/core/api-route-protection.js.map +1 -0
- package/dist/checks/core/critical.d.ts +8 -0
- package/dist/checks/core/critical.d.ts.map +1 -0
- package/dist/checks/core/critical.js +200 -0
- package/dist/checks/core/critical.js.map +1 -0
- package/dist/checks/core/database.d.ts +8 -0
- package/dist/checks/core/database.d.ts.map +1 -0
- package/dist/checks/core/database.js +699 -0
- package/dist/checks/core/database.js.map +1 -0
- package/dist/checks/core/development.d.ts +8 -0
- package/dist/checks/core/development.d.ts.map +1 -0
- package/dist/checks/core/development.js +417 -0
- package/dist/checks/core/development.js.map +1 -0
- package/dist/checks/core/hydration-mismatch-check.d.ts +38 -0
- package/dist/checks/core/hydration-mismatch-check.d.ts.map +1 -0
- package/dist/checks/core/hydration-mismatch-check.js +411 -0
- package/dist/checks/core/hydration-mismatch-check.js.map +1 -0
- package/dist/checks/core/performance.d.ts +8 -0
- package/dist/checks/core/performance.d.ts.map +1 -0
- package/dist/checks/core/performance.js +474 -0
- package/dist/checks/core/performance.js.map +1 -0
- package/dist/checks/core/security.d.ts +8 -0
- package/dist/checks/core/security.d.ts.map +1 -0
- package/dist/checks/core/security.js +275 -0
- package/dist/checks/core/security.js.map +1 -0
- package/dist/checks/core/standardized-error-handling.d.ts +43 -0
- package/dist/checks/core/standardized-error-handling.d.ts.map +1 -0
- package/dist/checks/core/standardized-error-handling.js +384 -0
- package/dist/checks/core/standardized-error-handling.js.map +1 -0
- package/dist/checks/core/supercatch.d.ts +8 -0
- package/dist/checks/core/supercatch.d.ts.map +1 -0
- package/dist/checks/core/supercatch.js +750 -0
- package/dist/checks/core/supercatch.js.map +1 -0
- package/dist/checks/core/suppression-check.d.ts +2 -0
- package/dist/checks/core/suppression-check.d.ts.map +1 -0
- package/dist/checks/core/suppression-check.js +129 -0
- package/dist/checks/core/suppression-check.js.map +1 -0
- package/dist/checks/core/ui-quality.d.ts +8 -0
- package/dist/checks/core/ui-quality.d.ts.map +1 -0
- package/dist/checks/core/ui-quality.js +1736 -0
- package/dist/checks/core/ui-quality.js.map +1 -0
- package/dist/checks/core/unused-assets-check.d.ts +2 -0
- package/dist/checks/core/unused-assets-check.d.ts.map +1 -0
- package/dist/checks/core/unused-assets-check.js +112 -0
- package/dist/checks/core/unused-assets-check.js.map +1 -0
- package/dist/checks/core/use-status-ssr-safety.d.ts +34 -0
- package/dist/checks/core/use-status-ssr-safety.d.ts.map +1 -0
- package/dist/checks/core/use-status-ssr-safety.js +283 -0
- package/dist/checks/core/use-status-ssr-safety.js.map +1 -0
- package/dist/checks/email/email-flow-validation.d.ts +23 -0
- package/dist/checks/email/email-flow-validation.d.ts.map +1 -0
- package/dist/checks/email/email-flow-validation.js +468 -0
- package/dist/checks/email/email-flow-validation.js.map +1 -0
- package/dist/checks/email/email-template-db-verification.d.ts +20 -0
- package/dist/checks/email/email-template-db-verification.d.ts.map +1 -0
- package/dist/checks/email/email-template-db-verification.js +46 -0
- package/dist/checks/email/email-template-db-verification.js.map +1 -0
- package/dist/checks/email/email-template-validation.d.ts +24 -0
- package/dist/checks/email/email-template-validation.d.ts.map +1 -0
- package/dist/checks/email/email-template-validation.js +688 -0
- package/dist/checks/email/email-template-validation.js.map +1 -0
- package/dist/checks/jsx/comment-placement.d.ts +45 -0
- package/dist/checks/jsx/comment-placement.d.ts.map +1 -0
- package/dist/checks/jsx/comment-placement.js +316 -0
- package/dist/checks/jsx/comment-placement.js.map +1 -0
- package/dist/checks/specialized/admin-layout-check.d.ts +19 -0
- package/dist/checks/specialized/admin-layout-check.d.ts.map +1 -0
- package/dist/checks/specialized/admin-layout-check.js +166 -0
- package/dist/checks/specialized/admin-layout-check.js.map +1 -0
- package/dist/checks/specialized/client-server-separation.d.ts +14 -0
- package/dist/checks/specialized/client-server-separation.d.ts.map +1 -0
- package/dist/checks/specialized/client-server-separation.js +197 -0
- package/dist/checks/specialized/client-server-separation.js.map +1 -0
- package/dist/checks/specialized/cost-optimization.d.ts +18 -0
- package/dist/checks/specialized/cost-optimization.d.ts.map +1 -0
- package/dist/checks/specialized/cost-optimization.js +78 -0
- package/dist/checks/specialized/cost-optimization.js.map +1 -0
- package/dist/checks/specialized/database-migration-sync.d.ts +21 -0
- package/dist/checks/specialized/database-migration-sync.d.ts.map +1 -0
- package/dist/checks/specialized/database-migration-sync.js +150 -0
- package/dist/checks/specialized/database-migration-sync.js.map +1 -0
- package/dist/checks/specialized/database-model-validation.d.ts +15 -0
- package/dist/checks/specialized/database-model-validation.d.ts.map +1 -0
- package/dist/checks/specialized/database-model-validation.js +35 -0
- package/dist/checks/specialized/database-model-validation.js.map +1 -0
- package/dist/checks/specialized/database-schema-migrations-diff.d.ts +27 -0
- package/dist/checks/specialized/database-schema-migrations-diff.d.ts.map +1 -0
- package/dist/checks/specialized/database-schema-migrations-diff.js +177 -0
- package/dist/checks/specialized/database-schema-migrations-diff.js.map +1 -0
- package/dist/checks/specialized/database-schema-sync.d.ts +23 -0
- package/dist/checks/specialized/database-schema-sync.d.ts.map +1 -0
- package/dist/checks/specialized/database-schema-sync.js +77 -0
- package/dist/checks/specialized/database-schema-sync.js.map +1 -0
- package/dist/checks/specialized/decimal-serialization.d.ts +24 -0
- package/dist/checks/specialized/decimal-serialization.d.ts.map +1 -0
- package/dist/checks/specialized/decimal-serialization.js +400 -0
- package/dist/checks/specialized/decimal-serialization.js.map +1 -0
- package/dist/checks/specialized/detect-router-issues.d.ts +14 -0
- package/dist/checks/specialized/detect-router-issues.d.ts.map +1 -0
- package/dist/checks/specialized/detect-router-issues.js +96 -0
- package/dist/checks/specialized/detect-router-issues.js.map +1 -0
- package/dist/checks/specialized/enum-validation.d.ts +15 -0
- package/dist/checks/specialized/enum-validation.d.ts.map +1 -0
- package/dist/checks/specialized/enum-validation.js +35 -0
- package/dist/checks/specialized/enum-validation.js.map +1 -0
- package/dist/checks/specialized/hash-collision.d.ts +18 -0
- package/dist/checks/specialized/hash-collision.d.ts.map +1 -0
- package/dist/checks/specialized/hash-collision.js +78 -0
- package/dist/checks/specialized/hash-collision.js.map +1 -0
- package/dist/checks/specialized/id-generation-enforcement.d.ts +16 -0
- package/dist/checks/specialized/id-generation-enforcement.d.ts.map +1 -0
- package/dist/checks/specialized/id-generation-enforcement.js +307 -0
- package/dist/checks/specialized/id-generation-enforcement.js.map +1 -0
- package/dist/checks/specialized/image-data-integrity.d.ts +15 -0
- package/dist/checks/specialized/image-data-integrity.d.ts.map +1 -0
- package/dist/checks/specialized/image-data-integrity.js +79 -0
- package/dist/checks/specialized/image-data-integrity.js.map +1 -0
- package/dist/checks/specialized/image-health.d.ts +14 -0
- package/dist/checks/specialized/image-health.d.ts.map +1 -0
- package/dist/checks/specialized/image-health.js +122 -0
- package/dist/checks/specialized/image-health.js.map +1 -0
- package/dist/checks/specialized/image-metadata-validation.d.ts +14 -0
- package/dist/checks/specialized/image-metadata-validation.d.ts.map +1 -0
- package/dist/checks/specialized/image-metadata-validation.js +95 -0
- package/dist/checks/specialized/image-metadata-validation.js.map +1 -0
- package/dist/checks/specialized/image-optimization.d.ts +16 -0
- package/dist/checks/specialized/image-optimization.d.ts.map +1 -0
- package/dist/checks/specialized/image-optimization.js +86 -0
- package/dist/checks/specialized/image-optimization.js.map +1 -0
- package/dist/checks/specialized/invalid-module-imports.d.ts +24 -0
- package/dist/checks/specialized/invalid-module-imports.d.ts.map +1 -0
- package/dist/checks/specialized/invalid-module-imports.js +209 -0
- package/dist/checks/specialized/invalid-module-imports.js.map +1 -0
- package/dist/checks/specialized/lint-validation.d.ts +26 -0
- package/dist/checks/specialized/lint-validation.d.ts.map +1 -0
- package/dist/checks/specialized/lint-validation.js +193 -0
- package/dist/checks/specialized/lint-validation.js.map +1 -0
- package/dist/checks/specialized/listing-workflow.d.ts +19 -0
- package/dist/checks/specialized/listing-workflow.d.ts.map +1 -0
- package/dist/checks/specialized/listing-workflow.js +89 -0
- package/dist/checks/specialized/listing-workflow.js.map +1 -0
- package/dist/checks/specialized/mui-imports-validation.d.ts +18 -0
- package/dist/checks/specialized/mui-imports-validation.d.ts.map +1 -0
- package/dist/checks/specialized/mui-imports-validation.js +134 -0
- package/dist/checks/specialized/mui-imports-validation.js.map +1 -0
- package/dist/checks/specialized/nextauth-v5-compliance.d.ts +16 -0
- package/dist/checks/specialized/nextauth-v5-compliance.d.ts.map +1 -0
- package/dist/checks/specialized/nextauth-v5-compliance.js +164 -0
- package/dist/checks/specialized/nextauth-v5-compliance.js.map +1 -0
- package/dist/checks/specialized/nextjs-params-check.d.ts +14 -0
- package/dist/checks/specialized/nextjs-params-check.d.ts.map +1 -0
- package/dist/checks/specialized/nextjs-params-check.js +140 -0
- package/dist/checks/specialized/nextjs-params-check.js.map +1 -0
- package/dist/checks/specialized/no-legacy-catalog-aliases-validation.d.ts +16 -0
- package/dist/checks/specialized/no-legacy-catalog-aliases-validation.d.ts.map +1 -0
- package/dist/checks/specialized/no-legacy-catalog-aliases-validation.js +36 -0
- package/dist/checks/specialized/no-legacy-catalog-aliases-validation.js.map +1 -0
- package/dist/checks/specialized/no-wata-cardgraded-validation.d.ts +22 -0
- package/dist/checks/specialized/no-wata-cardgraded-validation.d.ts.map +1 -0
- package/dist/checks/specialized/no-wata-cardgraded-validation.js +97 -0
- package/dist/checks/specialized/no-wata-cardgraded-validation.js.map +1 -0
- package/dist/checks/specialized/parameter-consistency-check.d.ts +20 -0
- package/dist/checks/specialized/parameter-consistency-check.d.ts.map +1 -0
- package/dist/checks/specialized/parameter-consistency-check.js +115 -0
- package/dist/checks/specialized/parameter-consistency-check.js.map +1 -0
- package/dist/checks/specialized/prisma-field-names-validation.d.ts +15 -0
- package/dist/checks/specialized/prisma-field-names-validation.d.ts.map +1 -0
- package/dist/checks/specialized/prisma-field-names-validation.js +35 -0
- package/dist/checks/specialized/prisma-field-names-validation.js.map +1 -0
- package/dist/checks/specialized/prisma-null-syntax.d.ts +34 -0
- package/dist/checks/specialized/prisma-null-syntax.d.ts.map +1 -0
- package/dist/checks/specialized/prisma-null-syntax.js +330 -0
- package/dist/checks/specialized/prisma-null-syntax.js.map +1 -0
- package/dist/checks/specialized/prisma-query-validation.d.ts +15 -0
- package/dist/checks/specialized/prisma-query-validation.d.ts.map +1 -0
- package/dist/checks/specialized/prisma-query-validation.js +35 -0
- package/dist/checks/specialized/prisma-query-validation.js.map +1 -0
- package/dist/checks/specialized/product-type-validation.d.ts +17 -0
- package/dist/checks/specialized/product-type-validation.d.ts.map +1 -0
- package/dist/checks/specialized/product-type-validation.js +129 -0
- package/dist/checks/specialized/product-type-validation.js.map +1 -0
- package/dist/checks/specialized/responsive-image-validation.d.ts +14 -0
- package/dist/checks/specialized/responsive-image-validation.d.ts.map +1 -0
- package/dist/checks/specialized/responsive-image-validation.js +101 -0
- package/dist/checks/specialized/responsive-image-validation.js.map +1 -0
- package/dist/checks/specialized/root-cleanliness.d.ts +21 -0
- package/dist/checks/specialized/root-cleanliness.d.ts.map +1 -0
- package/dist/checks/specialized/root-cleanliness.js +251 -0
- package/dist/checks/specialized/root-cleanliness.js.map +1 -0
- package/dist/checks/specialized/rotation-detection-validation.d.ts +16 -0
- package/dist/checks/specialized/rotation-detection-validation.d.ts.map +1 -0
- package/dist/checks/specialized/rotation-detection-validation.js +113 -0
- package/dist/checks/specialized/rotation-detection-validation.js.map +1 -0
- package/dist/checks/specialized/script-organization.d.ts +17 -0
- package/dist/checks/specialized/script-organization.d.ts.map +1 -0
- package/dist/checks/specialized/script-organization.js +487 -0
- package/dist/checks/specialized/script-organization.js.map +1 -0
- package/dist/checks/specialized/shared-components-migration.d.ts +137 -0
- package/dist/checks/specialized/shared-components-migration.d.ts.map +1 -0
- package/dist/checks/specialized/shared-components-migration.js +1288 -0
- package/dist/checks/specialized/shared-components-migration.js.map +1 -0
- package/dist/checks/specialized/store-specialties-normalization.d.ts +10 -0
- package/dist/checks/specialized/store-specialties-normalization.d.ts.map +1 -0
- package/dist/checks/specialized/store-specialties-normalization.js +126 -0
- package/dist/checks/specialized/store-specialties-normalization.js.map +1 -0
- package/dist/checks/specialized/two-stage-trim-validation.d.ts +16 -0
- package/dist/checks/specialized/two-stage-trim-validation.d.ts.map +1 -0
- package/dist/checks/specialized/two-stage-trim-validation.js +115 -0
- package/dist/checks/specialized/two-stage-trim-validation.js.map +1 -0
- package/dist/checks/specialized/underscore-variable-audit.d.ts +26 -0
- package/dist/checks/specialized/underscore-variable-audit.d.ts.map +1 -0
- package/dist/checks/specialized/underscore-variable-audit.js +219 -0
- package/dist/checks/specialized/underscore-variable-audit.js.map +1 -0
- package/dist/checks/specialized/unified-badge-consistency.d.ts +16 -0
- package/dist/checks/specialized/unified-badge-consistency.d.ts.map +1 -0
- package/dist/checks/specialized/unified-badge-consistency.js +284 -0
- package/dist/checks/specialized/unified-badge-consistency.js.map +1 -0
- package/dist/checks/specialized/validate-integration-enums.d.ts +15 -0
- package/dist/checks/specialized/validate-integration-enums.d.ts.map +1 -0
- package/dist/checks/specialized/validate-integration-enums.js +131 -0
- package/dist/checks/specialized/validate-integration-enums.js.map +1 -0
- package/dist/checks/testing/action-regression.d.ts +23 -0
- package/dist/checks/testing/action-regression.d.ts.map +1 -0
- package/dist/checks/testing/action-regression.js +192 -0
- package/dist/checks/testing/action-regression.js.map +1 -0
- package/dist/checks/testing/critical-api-coverage.d.ts +21 -0
- package/dist/checks/testing/critical-api-coverage.d.ts.map +1 -0
- package/dist/checks/testing/critical-api-coverage.js +158 -0
- package/dist/checks/testing/critical-api-coverage.js.map +1 -0
- package/dist/checks/testing/data-entry-regression-required.d.ts +24 -0
- package/dist/checks/testing/data-entry-regression-required.d.ts.map +1 -0
- package/dist/checks/testing/data-entry-regression-required.js +378 -0
- package/dist/checks/testing/data-entry-regression-required.js.map +1 -0
- package/dist/checks/testing/e2e-best-practices.d.ts +24 -0
- package/dist/checks/testing/e2e-best-practices.d.ts.map +1 -0
- package/dist/checks/testing/e2e-best-practices.js +791 -0
- package/dist/checks/testing/e2e-best-practices.js.map +1 -0
- package/dist/checks/testing/e2e-flake-patterns.d.ts +26 -0
- package/dist/checks/testing/e2e-flake-patterns.d.ts.map +1 -0
- package/dist/checks/testing/e2e-flake-patterns.js +305 -0
- package/dist/checks/testing/e2e-flake-patterns.js.map +1 -0
- package/dist/checks/testing/e2e-redundant-visibility-checks.d.ts +25 -0
- package/dist/checks/testing/e2e-redundant-visibility-checks.d.ts.map +1 -0
- package/dist/checks/testing/e2e-redundant-visibility-checks.js +613 -0
- package/dist/checks/testing/e2e-redundant-visibility-checks.js.map +1 -0
- package/dist/checks/testing/e2e-slow-tests.d.ts +9 -0
- package/dist/checks/testing/e2e-slow-tests.d.ts.map +1 -0
- package/dist/checks/testing/e2e-slow-tests.js +142 -0
- package/dist/checks/testing/e2e-slow-tests.js.map +1 -0
- package/dist/checks/testing/e2e-timeouts.d.ts +9 -0
- package/dist/checks/testing/e2e-timeouts.d.ts.map +1 -0
- package/dist/checks/testing/e2e-timeouts.js +82 -0
- package/dist/checks/testing/e2e-timeouts.js.map +1 -0
- package/dist/checks/testing/integration-e2e-depth.d.ts +20 -0
- package/dist/checks/testing/integration-e2e-depth.d.ts.map +1 -0
- package/dist/checks/testing/integration-e2e-depth.js +575 -0
- package/dist/checks/testing/integration-e2e-depth.js.map +1 -0
- package/dist/checks/testing/playwright-feature-coverage-gaps.d.ts +31 -0
- package/dist/checks/testing/playwright-feature-coverage-gaps.d.ts.map +1 -0
- package/dist/checks/testing/playwright-feature-coverage-gaps.js +1582 -0
- package/dist/checks/testing/playwright-feature-coverage-gaps.js.map +1 -0
- package/dist/checks/testing/playwright-mock-inventory.d.ts +24 -0
- package/dist/checks/testing/playwright-mock-inventory.d.ts.map +1 -0
- package/dist/checks/testing/playwright-mock-inventory.js +380 -0
- package/dist/checks/testing/playwright-mock-inventory.js.map +1 -0
- package/dist/checks/testing/test-coverage-threshold.d.ts +25 -0
- package/dist/checks/testing/test-coverage-threshold.d.ts.map +1 -0
- package/dist/checks/testing/test-coverage-threshold.js +166 -0
- package/dist/checks/testing/test-coverage-threshold.js.map +1 -0
- package/dist/checks/testing/test-flakiness-score.d.ts +27 -0
- package/dist/checks/testing/test-flakiness-score.d.ts.map +1 -0
- package/dist/checks/testing/test-flakiness-score.js +358 -0
- package/dist/checks/testing/test-flakiness-score.js.map +1 -0
- package/dist/checks/testing/test-patterns.d.ts +16 -0
- package/dist/checks/testing/test-patterns.d.ts.map +1 -0
- package/dist/checks/testing/test-patterns.js +156 -0
- package/dist/checks/testing/test-patterns.js.map +1 -0
- package/dist/checks/workflows/a-plus-rating-validation.d.ts +42 -0
- package/dist/checks/workflows/a-plus-rating-validation.d.ts.map +1 -0
- package/dist/checks/workflows/a-plus-rating-validation.js +527 -0
- package/dist/checks/workflows/a-plus-rating-validation.js.map +1 -0
- package/dist/checks/workflows/affected.d.ts +14 -0
- package/dist/checks/workflows/affected.d.ts.map +1 -0
- package/dist/checks/workflows/affected.js +126 -0
- package/dist/checks/workflows/affected.js.map +1 -0
- package/dist/checks/workflows/ai.d.ts +6 -0
- package/dist/checks/workflows/ai.d.ts.map +1 -0
- package/dist/checks/workflows/ai.js +42 -0
- package/dist/checks/workflows/ai.js.map +1 -0
- package/dist/checks/workflows/all.d.ts +31 -0
- package/dist/checks/workflows/all.d.ts.map +1 -0
- package/dist/checks/workflows/all.js +2688 -0
- package/dist/checks/workflows/all.js.map +1 -0
- package/dist/checks/workflows/commit.d.ts +19 -0
- package/dist/checks/workflows/commit.d.ts.map +1 -0
- package/dist/checks/workflows/commit.js +207 -0
- package/dist/checks/workflows/commit.js.map +1 -0
- package/dist/checks/workflows/critical.d.ts +9 -0
- package/dist/checks/workflows/critical.d.ts.map +1 -0
- package/dist/checks/workflows/critical.js +213 -0
- package/dist/checks/workflows/critical.js.map +1 -0
- package/dist/checks/workflows/database-id-validation.d.ts +9 -0
- package/dist/checks/workflows/database-id-validation.d.ts.map +1 -0
- package/dist/checks/workflows/database-id-validation.js +13 -0
- package/dist/checks/workflows/database-id-validation.js.map +1 -0
- package/dist/checks/workflows/deploy.d.ts +20 -0
- package/dist/checks/workflows/deploy.d.ts.map +1 -0
- package/dist/checks/workflows/deploy.js +107 -0
- package/dist/checks/workflows/deploy.js.map +1 -0
- package/dist/checks/workflows/deployment-readiness.d.ts +12 -0
- package/dist/checks/workflows/deployment-readiness.d.ts.map +1 -0
- package/dist/checks/workflows/deployment-readiness.js +403 -0
- package/dist/checks/workflows/deployment-readiness.js.map +1 -0
- package/dist/checks/workflows/dev.d.ts +19 -0
- package/dist/checks/workflows/dev.d.ts.map +1 -0
- package/dist/checks/workflows/dev.js +88 -0
- package/dist/checks/workflows/dev.js.map +1 -0
- package/dist/checks/workflows/development.d.ts +9 -0
- package/dist/checks/workflows/development.d.ts.map +1 -0
- package/dist/checks/workflows/development.js +65 -0
- package/dist/checks/workflows/development.js.map +1 -0
- package/dist/checks/workflows/enterprise.d.ts +10 -0
- package/dist/checks/workflows/enterprise.d.ts.map +1 -0
- package/dist/checks/workflows/enterprise.js +359 -0
- package/dist/checks/workflows/enterprise.js.map +1 -0
- package/dist/checks/workflows/images.d.ts +6 -0
- package/dist/checks/workflows/images.d.ts.map +1 -0
- package/dist/checks/workflows/images.js +58 -0
- package/dist/checks/workflows/images.js.map +1 -0
- package/dist/checks/workflows/naming.d.ts +19 -0
- package/dist/checks/workflows/naming.d.ts.map +1 -0
- package/dist/checks/workflows/naming.js +42 -0
- package/dist/checks/workflows/naming.js.map +1 -0
- package/dist/checks/workflows/performance.d.ts +8 -0
- package/dist/checks/workflows/performance.d.ts.map +1 -0
- package/dist/checks/workflows/performance.js +77 -0
- package/dist/checks/workflows/performance.js.map +1 -0
- package/dist/checks/workflows/pre-deploy.d.ts +6 -0
- package/dist/checks/workflows/pre-deploy.d.ts.map +1 -0
- package/dist/checks/workflows/pre-deploy.js +41 -0
- package/dist/checks/workflows/pre-deploy.js.map +1 -0
- package/dist/checks/workflows/security.d.ts +8 -0
- package/dist/checks/workflows/security.d.ts.map +1 -0
- package/dist/checks/workflows/security.js +71 -0
- package/dist/checks/workflows/security.js.map +1 -0
- package/dist/checks/workflows/supercatch.d.ts +8 -0
- package/dist/checks/workflows/supercatch.d.ts.map +1 -0
- package/dist/checks/workflows/supercatch.js +127 -0
- package/dist/checks/workflows/supercatch.js.map +1 -0
- package/dist/checks/workflows/ui-quality.d.ts +9 -0
- package/dist/checks/workflows/ui-quality.d.ts.map +1 -0
- package/dist/checks/workflows/ui-quality.js +264 -0
- package/dist/checks/workflows/ui-quality.js.map +1 -0
- package/dist/checks/workflows/ui-uniformity.d.ts +18 -0
- package/dist/checks/workflows/ui-uniformity.d.ts.map +1 -0
- package/dist/checks/workflows/ui-uniformity.js +265 -0
- package/dist/checks/workflows/ui-uniformity.js.map +1 -0
- package/dist/checks/workflows/vercel.d.ts +16 -0
- package/dist/checks/workflows/vercel.d.ts.map +1 -0
- package/dist/checks/workflows/vercel.js +173 -0
- package/dist/checks/workflows/vercel.js.map +1 -0
- package/dist/utils/validation-helpers.d.ts +43 -0
- package/dist/utils/validation-helpers.d.ts.map +1 -0
- package/dist/utils/validation-helpers.js +370 -0
- package/dist/utils/validation-helpers.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1532 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Consolidated UI Patterns Preflight
|
|
5
|
+
*
|
|
6
|
+
* Combines remaining UI pattern checks into one module:
|
|
7
|
+
* - category-chip-consistency (UnifiedHeader category validation)
|
|
8
|
+
* - chip-size-consistency (StatusChip/CategoryChip size enforcement)
|
|
9
|
+
* - glassmorphism-enforcement (glass design tokens)
|
|
10
|
+
* - flex-justify-consistency (flex layout patterns)
|
|
11
|
+
* - lucide-icon-validation (icon imports)
|
|
12
|
+
* - css-circular-reference-check (CSS circular refs)
|
|
13
|
+
* - z-index-enforcement (z-index tokens)
|
|
14
|
+
* - undefined-css-variables (missing CSS variable definitions)
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* pnpm preflight:ui-patterns # All pattern checks
|
|
18
|
+
* pnpm preflight:ui-patterns category # Category chip consistency only
|
|
19
|
+
* pnpm preflight:ui-patterns chip-size # Chip size consistency only
|
|
20
|
+
* pnpm preflight:ui-patterns glass # Glassmorphism only
|
|
21
|
+
* pnpm preflight:ui-patterns flex # Flex justify only
|
|
22
|
+
* pnpm preflight:ui-patterns icons # Lucide icons only
|
|
23
|
+
* pnpm preflight:ui-patterns polish # Global UI polish warnings (padding/overlay spacing)
|
|
24
|
+
* pnpm preflight:ui-patterns cta # CTA buttons (detect Link/a styled like buttons)
|
|
25
|
+
* pnpm preflight:ui-patterns css # CSS circular refs only
|
|
26
|
+
* pnpm preflight:ui-patterns zindex # Z-index only
|
|
27
|
+
* pnpm preflight:ui-patterns undefined # Undefined CSS variables only
|
|
28
|
+
*/
|
|
29
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
30
|
+
if (k2 === undefined) k2 = k;
|
|
31
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
32
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
33
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
34
|
+
}
|
|
35
|
+
Object.defineProperty(o, k2, desc);
|
|
36
|
+
}) : (function(o, m, k, k2) {
|
|
37
|
+
if (k2 === undefined) k2 = k;
|
|
38
|
+
o[k2] = m[k];
|
|
39
|
+
}));
|
|
40
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
41
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
42
|
+
}) : function(o, v) {
|
|
43
|
+
o["default"] = v;
|
|
44
|
+
});
|
|
45
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
46
|
+
var ownKeys = function(o) {
|
|
47
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
48
|
+
var ar = [];
|
|
49
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
50
|
+
return ar;
|
|
51
|
+
};
|
|
52
|
+
return ownKeys(o);
|
|
53
|
+
};
|
|
54
|
+
return function (mod) {
|
|
55
|
+
if (mod && mod.__esModule) return mod;
|
|
56
|
+
var result = {};
|
|
57
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
58
|
+
__setModuleDefault(result, mod);
|
|
59
|
+
return result;
|
|
60
|
+
};
|
|
61
|
+
})();
|
|
62
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
63
|
+
exports.UIPatternsPreflightModule = void 0;
|
|
64
|
+
const fs = __importStar(require("fs"));
|
|
65
|
+
const path = __importStar(require("path"));
|
|
66
|
+
const console_chars_1 = require("../../utils/console-chars");
|
|
67
|
+
const universal_progress_reporter_1 = require("../system/universal-progress-reporter");
|
|
68
|
+
const file_cache_1 = require("../../shared/file-cache");
|
|
69
|
+
const glob_patterns_1 = require("../../shared/glob-patterns");
|
|
70
|
+
const concurrency_config_1 = require("../../shared/concurrency-config");
|
|
71
|
+
const EXCLUDED = [...glob_patterns_1.STANDARD_EXCLUDES];
|
|
72
|
+
// Cache for getAllTsxJsxFiles
|
|
73
|
+
let _cachedAllTsxJsxFiles = null;
|
|
74
|
+
async function getAllTsxJsxFiles() {
|
|
75
|
+
if (!_cachedAllTsxJsxFiles) {
|
|
76
|
+
_cachedAllTsxJsxFiles = await file_cache_1.fileCache.getAllTsxJsx();
|
|
77
|
+
}
|
|
78
|
+
return _cachedAllTsxJsxFiles;
|
|
79
|
+
}
|
|
80
|
+
// Cache for getAllTsTsxFiles
|
|
81
|
+
let _cachedAllTsTsxFiles = null;
|
|
82
|
+
async function getAllTsTsxFiles() {
|
|
83
|
+
if (!_cachedAllTsTsxFiles) {
|
|
84
|
+
_cachedAllTsTsxFiles = await file_cache_1.fileCache.getAllTsTsx();
|
|
85
|
+
}
|
|
86
|
+
return _cachedAllTsTsxFiles;
|
|
87
|
+
}
|
|
88
|
+
// Cache for getCSSFiles
|
|
89
|
+
let _cachedCSSFiles = null;
|
|
90
|
+
async function getCSSFiles() {
|
|
91
|
+
if (!_cachedCSSFiles) {
|
|
92
|
+
_cachedCSSFiles = await file_cache_1.fileCache.getFiles("**/*.css", { ignore: EXCLUDED });
|
|
93
|
+
}
|
|
94
|
+
return _cachedCSSFiles;
|
|
95
|
+
}
|
|
96
|
+
// Cache for defined CSS variables from tokens.css
|
|
97
|
+
let definedCssVariables = null;
|
|
98
|
+
// Standardized category labels for UnifiedHeader (must match lib/category-chip-constants.ts)
|
|
99
|
+
const VALID_CATEGORIES = new Set([
|
|
100
|
+
// Seller Categories
|
|
101
|
+
"Seller",
|
|
102
|
+
"Seller Store",
|
|
103
|
+
"Seller Tools",
|
|
104
|
+
"Listings",
|
|
105
|
+
"Sales",
|
|
106
|
+
"Orders",
|
|
107
|
+
"Order Details",
|
|
108
|
+
"Performance",
|
|
109
|
+
"Store",
|
|
110
|
+
"Store Management",
|
|
111
|
+
"Store Settings",
|
|
112
|
+
"Settings",
|
|
113
|
+
"Configuration",
|
|
114
|
+
"Integration",
|
|
115
|
+
"Developer Tools",
|
|
116
|
+
"Team",
|
|
117
|
+
// Admin Categories
|
|
118
|
+
"Admin",
|
|
119
|
+
"Administration",
|
|
120
|
+
"Integrations",
|
|
121
|
+
"Content Moderation",
|
|
122
|
+
"Marketing",
|
|
123
|
+
// Account/Personal Categories
|
|
124
|
+
"Account",
|
|
125
|
+
"Personal",
|
|
126
|
+
"Business",
|
|
127
|
+
// Marketplace Categories
|
|
128
|
+
"Marketplace",
|
|
129
|
+
"Collectibles",
|
|
130
|
+
"Sports Cards",
|
|
131
|
+
"Non-Sports Cards",
|
|
132
|
+
"Non-Sport Cards",
|
|
133
|
+
"Trading Card Games",
|
|
134
|
+
"Video Games",
|
|
135
|
+
"Tickets",
|
|
136
|
+
"Autographs",
|
|
137
|
+
]);
|
|
138
|
+
// Invalid lucide icons mapping
|
|
139
|
+
const INVALID_ICONS = {
|
|
140
|
+
Add: "Plus",
|
|
141
|
+
Autorenew: "RefreshCw",
|
|
142
|
+
LocalOffer: "Tag",
|
|
143
|
+
LocalShipping: "Truck",
|
|
144
|
+
LocationOn: "MapPin",
|
|
145
|
+
LockReset: "KeyRound",
|
|
146
|
+
MonetizationOn: "DollarSign",
|
|
147
|
+
MoreVert: "MoreVertical",
|
|
148
|
+
NavigateBefore: "ChevronLeft",
|
|
149
|
+
NavigateNext: "ChevronRight",
|
|
150
|
+
Notifications: "Bell",
|
|
151
|
+
Pending: "Clock",
|
|
152
|
+
Photo: "Image",
|
|
153
|
+
Remove: "Minus",
|
|
154
|
+
Restore: "RotateCcw",
|
|
155
|
+
StarBorder: "Star",
|
|
156
|
+
Storefront: "Store",
|
|
157
|
+
};
|
|
158
|
+
// CACHED FILE LISTS - Scan once, use everywhere
|
|
159
|
+
let _cachedAppComponentsTsxFiles = null;
|
|
160
|
+
async function getAppComponentsTsxFiles() {
|
|
161
|
+
if (!_cachedAppComponentsTsxFiles) {
|
|
162
|
+
_cachedAppComponentsTsxFiles = await file_cache_1.fileCache.getAppAndComponentsTSX();
|
|
163
|
+
}
|
|
164
|
+
return _cachedAppComponentsTsxFiles;
|
|
165
|
+
}
|
|
166
|
+
// Get concurrency from shared config (respects PREFLIGHT_CONCURRENCY env var)
|
|
167
|
+
const concurrencyConfig = (0, concurrency_config_1.getConcurrencyConfig)();
|
|
168
|
+
class UIPatternsPreflightModule {
|
|
169
|
+
verbose;
|
|
170
|
+
parallel = false;
|
|
171
|
+
strictUniformity;
|
|
172
|
+
constructor(options = {}) {
|
|
173
|
+
this.verbose = options.verbose || false;
|
|
174
|
+
this.parallel = options.parallel ?? concurrencyConfig.parallel;
|
|
175
|
+
this.strictUniformity =
|
|
176
|
+
typeof options.strictUniformity === "boolean"
|
|
177
|
+
? options.strictUniformity
|
|
178
|
+
: process.env.PREFLIGHT_STRICT_UNIFORMITY === "1";
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Category Chip Consistency - ensures UnifiedHeader category props use standardized labels
|
|
182
|
+
*/
|
|
183
|
+
async checkCategoryChips() {
|
|
184
|
+
const startTime = Date.now();
|
|
185
|
+
const issues = [];
|
|
186
|
+
const files = await getAppComponentsTsxFiles();
|
|
187
|
+
// Files to ignore (false positives)
|
|
188
|
+
const ignoreFiles = ["ProductTypeBadge.tsx", "cleanup-remaining-model-issues.ts"];
|
|
189
|
+
const categoryPattern = /category=["']([^"']+)["']/g;
|
|
190
|
+
for (const file of files) {
|
|
191
|
+
const normalizedFile = file.replace(/\\/g, "/");
|
|
192
|
+
if (ignoreFiles.some((ignored) => normalizedFile.includes(ignored)))
|
|
193
|
+
continue;
|
|
194
|
+
const content = fs.readFileSync(file, "utf8");
|
|
195
|
+
// Check if file uses UnifiedHeader with category prop
|
|
196
|
+
if (!content.includes("UnifiedHeader") && !content.includes("category="))
|
|
197
|
+
continue;
|
|
198
|
+
const lines = content.split("\n");
|
|
199
|
+
lines.forEach((line, index) => {
|
|
200
|
+
let match;
|
|
201
|
+
categoryPattern.lastIndex = 0;
|
|
202
|
+
while ((match = categoryPattern.exec(line)) !== null) {
|
|
203
|
+
const category = match[1];
|
|
204
|
+
if (!VALID_CATEGORIES.has(category)) {
|
|
205
|
+
issues.push({
|
|
206
|
+
file,
|
|
207
|
+
line: index + 1,
|
|
208
|
+
type: "non-standard-category",
|
|
209
|
+
severity: "error",
|
|
210
|
+
message: `Non-standard category: "${category}"`,
|
|
211
|
+
suggestion: `Use one of: ${Array.from(VALID_CATEGORIES).slice(0, 5).join(", ")}...`,
|
|
212
|
+
snippet: line.trim().substring(0, 80),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
219
|
+
return {
|
|
220
|
+
name: "Category Chip Consistency",
|
|
221
|
+
passed: !hasErrors,
|
|
222
|
+
blocking: true,
|
|
223
|
+
issues,
|
|
224
|
+
duration: Date.now() - startTime,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Chip Size Consistency - ensures StatusChip/CategoryChip use consistent sizing
|
|
229
|
+
*
|
|
230
|
+
* Standard sizes:
|
|
231
|
+
* - sm (20px): Default small chip - use for most status indicators, tags, metadata
|
|
232
|
+
* - md (22px): Medium chip - use sparingly for emphasis
|
|
233
|
+
* - lg (24px): Large chip - rarely needed, requires justification
|
|
234
|
+
* - xs (18px): Extra small - only for very compact contexts
|
|
235
|
+
*
|
|
236
|
+
* Product pages use sm as the standard. All other pages should match.
|
|
237
|
+
*
|
|
238
|
+
* Also detects:
|
|
239
|
+
* - Inline height/padding overrides that bypass the size system
|
|
240
|
+
* - Generic Chip component usage (should use StatusChip/CategoryChip)
|
|
241
|
+
* - Inconsistent chip sizing within the same component
|
|
242
|
+
*/
|
|
243
|
+
async checkChipSizeConsistency() {
|
|
244
|
+
const startTime = Date.now();
|
|
245
|
+
const issues = [];
|
|
246
|
+
const files = await getAppComponentsTsxFiles();
|
|
247
|
+
// Skip the component definitions themselves
|
|
248
|
+
const skipFiles = [
|
|
249
|
+
"StatusChip.tsx",
|
|
250
|
+
"Chip.tsx",
|
|
251
|
+
"FilterChip.tsx",
|
|
252
|
+
"CategoryChip.tsx",
|
|
253
|
+
"StatusIconChip.tsx",
|
|
254
|
+
];
|
|
255
|
+
for (const file of files) {
|
|
256
|
+
const normalizedFile = file.replace(/\\/g, "/");
|
|
257
|
+
if (skipFiles.some((skip) => normalizedFile.endsWith(skip)))
|
|
258
|
+
continue;
|
|
259
|
+
const content = fs.readFileSync(file, "utf8");
|
|
260
|
+
const lines = content.split("\n");
|
|
261
|
+
// Track chip sizes used in this file for consistency check
|
|
262
|
+
const chipSizesInFile = [];
|
|
263
|
+
// Check for StatusChip, CategoryChip, FilterChip with size prop
|
|
264
|
+
const chipPatterns = [
|
|
265
|
+
{ regex: /<StatusChip[^>]*\bsize=["'](\w+)["'][^>]*>/g, name: "StatusChip" },
|
|
266
|
+
{ regex: /<CategoryChip[^>]*\bsize=["'](\w+)["'][^>]*>/g, name: "CategoryChip" },
|
|
267
|
+
{ regex: /<FilterChip[^>]*\bsize=["'](\w+)["'][^>]*>/g, name: "FilterChip" },
|
|
268
|
+
];
|
|
269
|
+
for (const { regex: pattern, name: chipName } of chipPatterns) {
|
|
270
|
+
let match;
|
|
271
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
272
|
+
const lineNum = content.substring(0, match.index).split("\n").length;
|
|
273
|
+
const size = match[1];
|
|
274
|
+
const fullMatch = match[0];
|
|
275
|
+
// Check for preflight-ignore comment
|
|
276
|
+
const prevLine = lineNum > 1 ? lines[lineNum - 2] : "";
|
|
277
|
+
if (prevLine.includes("preflight-ignore") || prevLine.includes("chip-size-ok")) {
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
// Track for consistency check
|
|
281
|
+
chipSizesInFile.push({ size, line: lineNum });
|
|
282
|
+
// sm and xs are always OK (sm is standard, xs is for compact)
|
|
283
|
+
if (size === "sm" || size === "small" || size === "xs") {
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
// md is a warning - consider using sm
|
|
287
|
+
if (size === "md" || size === "medium") {
|
|
288
|
+
issues.push({
|
|
289
|
+
file,
|
|
290
|
+
line: lineNum,
|
|
291
|
+
type: "chip-size-medium",
|
|
292
|
+
severity: "warning",
|
|
293
|
+
message: `${chipName} uses size="${size}" - consider size="sm" for consistency`,
|
|
294
|
+
suggestion: `Use size="sm" (standard) or add /* chip-size-ok */ comment if md is intentional`,
|
|
295
|
+
snippet: fullMatch.substring(0, 80),
|
|
296
|
+
});
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
// lg is an error - rarely needed
|
|
300
|
+
if (size === "lg" || size === "large") {
|
|
301
|
+
issues.push({
|
|
302
|
+
file,
|
|
303
|
+
line: lineNum,
|
|
304
|
+
type: "chip-size-large",
|
|
305
|
+
severity: "error",
|
|
306
|
+
message: `${chipName} uses size="${size}" - large chips are rarely needed`,
|
|
307
|
+
suggestion: `Use size="sm" (standard) or size="md" (emphasis). Add /* chip-size-ok */ if lg is required.`,
|
|
308
|
+
snippet: fullMatch.substring(0, 80),
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// Check for inline height/padding overrides on chips (only when no size prop is set)
|
|
314
|
+
// This catches chips that bypass the size system entirely
|
|
315
|
+
const chipWithInlineStylePattern = /<(?:Status|Category|Filter)Chip\b(?![^>]*\bsize=)[^>]*(?:style=\{[^}]*(?:height|minHeight)[^}]*\})[^>]*>/g;
|
|
316
|
+
let heightMatch;
|
|
317
|
+
while ((heightMatch = chipWithInlineStylePattern.exec(content)) !== null) {
|
|
318
|
+
const lineNum = content.substring(0, heightMatch.index).split("\n").length;
|
|
319
|
+
const prevLine = lineNum > 1 ? lines[lineNum - 2] : "";
|
|
320
|
+
if (prevLine.includes("preflight-ignore") || prevLine.includes("chip-size-ok")) {
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
issues.push({
|
|
324
|
+
file,
|
|
325
|
+
line: lineNum,
|
|
326
|
+
type: "chip-height-override",
|
|
327
|
+
severity: "warning",
|
|
328
|
+
message: "Chip uses inline height style instead of size prop",
|
|
329
|
+
suggestion: 'Use size="sm" (20px), size="md" (22px), or size="lg" (24px) instead of inline height',
|
|
330
|
+
snippet: heightMatch[0].substring(0, 100),
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
// Check for chips with both size prop AND conflicting inline height (redundant/conflicting)
|
|
334
|
+
const redundantHeightPattern = /<(?:Status|Category|Filter)Chip\b[^>]*\bsize=["']\w+["'][^>]*style=\{[^}]*(?:height|minHeight)[^}]*\}[^>]*>/g;
|
|
335
|
+
let redundantMatch;
|
|
336
|
+
while ((redundantMatch = redundantHeightPattern.exec(content)) !== null) {
|
|
337
|
+
const lineNum = content.substring(0, redundantMatch.index).split("\n").length;
|
|
338
|
+
const prevLine = lineNum > 1 ? lines[lineNum - 2] : "";
|
|
339
|
+
if (prevLine.includes("preflight-ignore") || prevLine.includes("chip-size-ok")) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
issues.push({
|
|
343
|
+
file,
|
|
344
|
+
line: lineNum,
|
|
345
|
+
type: "chip-redundant-height",
|
|
346
|
+
severity: "info",
|
|
347
|
+
message: "Chip has both size prop and inline height - remove redundant inline style",
|
|
348
|
+
suggestion: "The size prop already sets the height. Remove the inline height style.",
|
|
349
|
+
snippet: redundantMatch[0].substring(0, 100),
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
// Check for generic <Chip> usage (should use StatusChip/CategoryChip)
|
|
353
|
+
const genericChipPattern = /<Chip\s+[^>]*(?:label|color)=[^>]*>/g;
|
|
354
|
+
let genericMatch;
|
|
355
|
+
while ((genericMatch = genericChipPattern.exec(content)) !== null) {
|
|
356
|
+
const lineNum = content.substring(0, genericMatch.index).split("\n").length;
|
|
357
|
+
const prevLine = lineNum > 1 ? lines[lineNum - 2] : "";
|
|
358
|
+
if (prevLine.includes("preflight-ignore") || prevLine.includes("chip-ok")) {
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
// Skip if it's in a comment
|
|
362
|
+
const line = lines[lineNum - 1];
|
|
363
|
+
if (line.trim().startsWith("//") || line.trim().startsWith("*")) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
issues.push({
|
|
367
|
+
file,
|
|
368
|
+
line: lineNum,
|
|
369
|
+
type: "generic-chip-usage",
|
|
370
|
+
severity: "info",
|
|
371
|
+
message: "Generic <Chip> component - consider using StatusChip or CategoryChip",
|
|
372
|
+
suggestion: "StatusChip provides consistent sizing and predefined status colors. CategoryChip is for tags/labels.",
|
|
373
|
+
snippet: genericMatch[0].substring(0, 80),
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
// Check for mixed chip sizes within the same file (consistency warning)
|
|
377
|
+
if (chipSizesInFile.length > 1) {
|
|
378
|
+
const uniqueSizes = new Set(chipSizesInFile.map((c) => {
|
|
379
|
+
// Normalize size names
|
|
380
|
+
if (c.size === "small")
|
|
381
|
+
return "sm";
|
|
382
|
+
if (c.size === "medium")
|
|
383
|
+
return "md";
|
|
384
|
+
if (c.size === "large")
|
|
385
|
+
return "lg";
|
|
386
|
+
return c.size;
|
|
387
|
+
}));
|
|
388
|
+
// If file has both sm and md (or other mixed sizes), warn about inconsistency
|
|
389
|
+
if (uniqueSizes.size > 1 && !uniqueSizes.has("xs")) {
|
|
390
|
+
const sizesUsed = Array.from(uniqueSizes).join(", ");
|
|
391
|
+
issues.push({
|
|
392
|
+
file,
|
|
393
|
+
line: chipSizesInFile[0].line,
|
|
394
|
+
type: "chip-size-inconsistent",
|
|
395
|
+
severity: "info",
|
|
396
|
+
message: `File uses multiple chip sizes (${sizesUsed}) - consider standardizing`,
|
|
397
|
+
suggestion: 'Use size="sm" consistently unless there\'s a specific reason for variation',
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const errorCount = issues.filter((i) => i.severity === "error").length;
|
|
403
|
+
const warningCount = issues.filter((i) => i.severity === "warning").length;
|
|
404
|
+
return {
|
|
405
|
+
name: `Chip Size Consistency (${errorCount} errors, ${warningCount} warnings)`,
|
|
406
|
+
passed: errorCount === 0,
|
|
407
|
+
blocking: true,
|
|
408
|
+
issues,
|
|
409
|
+
duration: Date.now() - startTime,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Glassmorphism Enforcement - ensures glass tokens are used
|
|
414
|
+
*/
|
|
415
|
+
async checkGlassmorphism() {
|
|
416
|
+
const startTime = Date.now();
|
|
417
|
+
const issues = [];
|
|
418
|
+
const files = await getAppComponentsTsxFiles();
|
|
419
|
+
for (const file of files) {
|
|
420
|
+
const content = fs.readFileSync(file, "utf8");
|
|
421
|
+
const lines = content.split("\n");
|
|
422
|
+
lines.forEach((line, index) => {
|
|
423
|
+
// Hardcoded backdrop-blur classes
|
|
424
|
+
const blurMatch = line.match(/backdrop-blur-(sm|md|lg|xl|2xl)/);
|
|
425
|
+
if (blurMatch) {
|
|
426
|
+
issues.push({
|
|
427
|
+
file,
|
|
428
|
+
line: index + 1,
|
|
429
|
+
type: "hardcoded-blur",
|
|
430
|
+
severity: "error",
|
|
431
|
+
message: `Hardcoded ${blurMatch[0]}`,
|
|
432
|
+
suggestion: `Use var(--glass-blur-${blurMatch[1]})`,
|
|
433
|
+
snippet: line.trim().substring(0, 80),
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
// Hardcoded rgba backgrounds on floating elements
|
|
437
|
+
if (/(?:backgroundColor|background):\s*["']rgba\((?:255,\s*255,\s*255|0,\s*0,\s*0),\s*0\.\d+\)/.test(line)) {
|
|
438
|
+
const context = lines
|
|
439
|
+
.slice(Math.max(0, index - 5), Math.min(lines.length, index + 5))
|
|
440
|
+
.join("\n");
|
|
441
|
+
if (/sticky|fixed|modal|dialog|drawer|popover/i.test(context)) {
|
|
442
|
+
issues.push({
|
|
443
|
+
file,
|
|
444
|
+
line: index + 1,
|
|
445
|
+
type: "hardcoded-glass-bg",
|
|
446
|
+
severity: "error",
|
|
447
|
+
message: "Hardcoded rgba() on floating element",
|
|
448
|
+
suggestion: "Use var(--glass-bg-*) tokens",
|
|
449
|
+
snippet: line.trim().substring(0, 80),
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
// Hardcoded transparency classes
|
|
454
|
+
const transparencyMatch = line.match(/bg-(?:white|black)\/\d+/);
|
|
455
|
+
if (transparencyMatch) {
|
|
456
|
+
const context = lines
|
|
457
|
+
.slice(Math.max(0, index - 5), Math.min(lines.length, index + 5))
|
|
458
|
+
.join("\n");
|
|
459
|
+
if (/sticky|fixed|modal|dialog|drawer|popover/i.test(context)) {
|
|
460
|
+
issues.push({
|
|
461
|
+
file,
|
|
462
|
+
line: index + 1,
|
|
463
|
+
type: "hardcoded-transparency",
|
|
464
|
+
severity: "warning",
|
|
465
|
+
message: `Hardcoded ${transparencyMatch[0]} on floating element`,
|
|
466
|
+
suggestion: "Use var(--glass-bg-*) tokens",
|
|
467
|
+
snippet: line.trim().substring(0, 80),
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
474
|
+
return {
|
|
475
|
+
name: "Glassmorphism Enforcement",
|
|
476
|
+
passed: !hasErrors,
|
|
477
|
+
blocking: true,
|
|
478
|
+
issues,
|
|
479
|
+
duration: Date.now() - startTime,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Flex Justify Consistency - detects problematic flex patterns
|
|
484
|
+
*/
|
|
485
|
+
async checkFlexJustify() {
|
|
486
|
+
const startTime = Date.now();
|
|
487
|
+
const issues = [];
|
|
488
|
+
const files = await getAllTsxJsxFiles();
|
|
489
|
+
for (const file of files) {
|
|
490
|
+
const content = fs.readFileSync(file, "utf8");
|
|
491
|
+
const lines = content.split("\n");
|
|
492
|
+
lines.forEach((line, index) => {
|
|
493
|
+
// Check for flex containers with wrap and center
|
|
494
|
+
if (/display:\s*["']flex["']/.test(line) &&
|
|
495
|
+
/flexWrap:\s*["']wrap["']/.test(line) &&
|
|
496
|
+
/justifyContent:\s*["']center["']/.test(line)) {
|
|
497
|
+
issues.push({
|
|
498
|
+
file,
|
|
499
|
+
line: index + 1,
|
|
500
|
+
type: "wrapped-flex-center",
|
|
501
|
+
severity: "warning",
|
|
502
|
+
message: 'flexWrap with justifyContent: "center" may cause centering issues',
|
|
503
|
+
suggestion: 'Use "flex-start", "flex-end", or "space-between"',
|
|
504
|
+
snippet: line.trim().substring(0, 80),
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
return {
|
|
510
|
+
name: "Flex Justify Consistency",
|
|
511
|
+
passed: true,
|
|
512
|
+
blocking: true,
|
|
513
|
+
issues,
|
|
514
|
+
duration: Date.now() - startTime,
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Lucide Icon Validation - ensures valid icon imports
|
|
519
|
+
*/
|
|
520
|
+
async checkLucideIcons() {
|
|
521
|
+
const startTime = Date.now();
|
|
522
|
+
const issues = [];
|
|
523
|
+
const files = await getAllTsTsxFiles();
|
|
524
|
+
for (const file of files) {
|
|
525
|
+
const content = fs.readFileSync(file, "utf8");
|
|
526
|
+
const importMatch = content.match(/import\s+{([^}]+)}\s+from\s+['"]lucide-react['"]/);
|
|
527
|
+
if (!importMatch)
|
|
528
|
+
continue;
|
|
529
|
+
const imports = importMatch[1]
|
|
530
|
+
.split(",")
|
|
531
|
+
.map((i) => i.trim())
|
|
532
|
+
.filter(Boolean);
|
|
533
|
+
const lineNumber = content.substring(0, importMatch.index).split("\n").length;
|
|
534
|
+
for (const icon of imports) {
|
|
535
|
+
const cleanIcon = icon.split(" as ")[0].trim();
|
|
536
|
+
if (INVALID_ICONS[cleanIcon]) {
|
|
537
|
+
issues.push({
|
|
538
|
+
file,
|
|
539
|
+
line: lineNumber,
|
|
540
|
+
type: "invalid-icon",
|
|
541
|
+
severity: "error",
|
|
542
|
+
message: `Invalid icon: ${cleanIcon}`,
|
|
543
|
+
suggestion: `Use ${INVALID_ICONS[cleanIcon]} instead`,
|
|
544
|
+
snippet: `import { ${cleanIcon} } from 'lucide-react'`,
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
550
|
+
return {
|
|
551
|
+
name: "Lucide Icon Validation",
|
|
552
|
+
passed: !hasErrors,
|
|
553
|
+
blocking: true,
|
|
554
|
+
issues,
|
|
555
|
+
duration: Date.now() - startTime,
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* CSS Circular Reference Check
|
|
560
|
+
*/
|
|
561
|
+
async checkCssCircular() {
|
|
562
|
+
const startTime = Date.now();
|
|
563
|
+
const issues = [];
|
|
564
|
+
const files = await getCSSFiles();
|
|
565
|
+
for (const file of files) {
|
|
566
|
+
const content = fs.readFileSync(file, "utf8");
|
|
567
|
+
const lines = content.split("\n");
|
|
568
|
+
// Track variable definitions
|
|
569
|
+
const varDefs = new Map();
|
|
570
|
+
lines.forEach((line, index) => {
|
|
571
|
+
const match = line.match(/--([a-zA-Z0-9-]+):\s*(.+);/);
|
|
572
|
+
if (match) {
|
|
573
|
+
varDefs.set(match[1], { line: index + 1, value: match[2] });
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
// Check for circular references
|
|
577
|
+
for (const [varName, { line, value }] of varDefs) {
|
|
578
|
+
const refs = value.match(/var\(--([a-zA-Z0-9-]+)\)/g) || [];
|
|
579
|
+
for (const ref of refs) {
|
|
580
|
+
const refName = ref.match(/--([a-zA-Z0-9-]+)/)?.[1];
|
|
581
|
+
if (refName && varDefs.has(refName)) {
|
|
582
|
+
const refValue = varDefs.get(refName).value;
|
|
583
|
+
if (refValue.includes(`var(--${varName})`)) {
|
|
584
|
+
issues.push({
|
|
585
|
+
file,
|
|
586
|
+
line,
|
|
587
|
+
type: "circular-ref",
|
|
588
|
+
severity: "error",
|
|
589
|
+
message: `Circular reference: --${varName} ↔ --${refName}`,
|
|
590
|
+
suggestion: "Break the circular dependency",
|
|
591
|
+
snippet: `--${varName}: ${value}`,
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
599
|
+
return {
|
|
600
|
+
name: "CSS Circular References",
|
|
601
|
+
passed: !hasErrors,
|
|
602
|
+
blocking: true,
|
|
603
|
+
issues,
|
|
604
|
+
duration: Date.now() - startTime,
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Autocomplete Floating Labels - enforce label-in-border UX site-wide.
|
|
609
|
+
*
|
|
610
|
+
* Our shared `Autocomplete` defaults to floating labels. Disallow opting out
|
|
611
|
+
* with `floatingLabel={false}` to keep forms consistent.
|
|
612
|
+
*/
|
|
613
|
+
async checkAutocompleteFloatingLabels() {
|
|
614
|
+
const startTime = Date.now();
|
|
615
|
+
const issues = [];
|
|
616
|
+
const files = await getAppComponentsTsxFiles();
|
|
617
|
+
for (const file of files) {
|
|
618
|
+
const content = fs.readFileSync(file, "utf8");
|
|
619
|
+
if (!content.includes("<Autocomplete"))
|
|
620
|
+
continue;
|
|
621
|
+
const lines = content.split("\n");
|
|
622
|
+
lines.forEach((line, index) => {
|
|
623
|
+
if (!line.includes("floatingLabel"))
|
|
624
|
+
return;
|
|
625
|
+
if (!/floatingLabel\s*=\s*\{?\s*false\s*\}?/.test(line))
|
|
626
|
+
return;
|
|
627
|
+
issues.push({
|
|
628
|
+
file,
|
|
629
|
+
line: index + 1,
|
|
630
|
+
type: "autocomplete-floatinglabel-disabled",
|
|
631
|
+
severity: "error",
|
|
632
|
+
message: "Autocomplete should use floating labels (do not disable floatingLabel)",
|
|
633
|
+
suggestion: "Remove `floatingLabel={false}` and rely on the shared Autocomplete default.",
|
|
634
|
+
snippet: line.trim().substring(0, 140),
|
|
635
|
+
});
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
639
|
+
return {
|
|
640
|
+
name: "Autocomplete Floating Labels",
|
|
641
|
+
passed: !hasErrors,
|
|
642
|
+
blocking: true,
|
|
643
|
+
issues,
|
|
644
|
+
duration: Date.now() - startTime,
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
/**
|
|
648
|
+
* Load defined CSS variables from all CSS files
|
|
649
|
+
*/
|
|
650
|
+
async loadDefinedCssVariables() {
|
|
651
|
+
if (definedCssVariables)
|
|
652
|
+
return definedCssVariables;
|
|
653
|
+
const variables = new Set();
|
|
654
|
+
// Scan all CSS files in the project for variable definitions
|
|
655
|
+
const cssFiles = await file_cache_1.fileCache.getFiles("{app,styles,packages}/**/*.css", {
|
|
656
|
+
ignore: ["**/node_modules/**", "**/.next/**"],
|
|
657
|
+
});
|
|
658
|
+
for (const cssFile of cssFiles) {
|
|
659
|
+
try {
|
|
660
|
+
const content = fs.readFileSync(cssFile, "utf8");
|
|
661
|
+
// Match CSS variable definitions: --variable-name:
|
|
662
|
+
const matches = content.matchAll(/--([a-zA-Z0-9-]+)\s*:/g);
|
|
663
|
+
for (const match of matches) {
|
|
664
|
+
variables.add(`--${match[1]}`);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
catch {
|
|
668
|
+
// File doesn't exist or can't be read, skip
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
definedCssVariables = variables;
|
|
672
|
+
return variables;
|
|
673
|
+
}
|
|
674
|
+
/**
|
|
675
|
+
* Undefined CSS Variables Check - detects var(--*) references to non-existent variables
|
|
676
|
+
*/
|
|
677
|
+
async checkUndefinedCssVariables() {
|
|
678
|
+
const startTime = Date.now();
|
|
679
|
+
const issues = [];
|
|
680
|
+
const files = await getAppComponentsTsxFiles();
|
|
681
|
+
const definedVars = await this.loadDefinedCssVariables();
|
|
682
|
+
// Common CSS variables that are defined elsewhere (browser defaults, Tailwind, etc.)
|
|
683
|
+
const knownExternalVars = new Set([
|
|
684
|
+
"--tw-", // Tailwind internal vars
|
|
685
|
+
"--radix-", // Radix UI vars
|
|
686
|
+
"--font-", // Next.js font vars
|
|
687
|
+
]);
|
|
688
|
+
const isKnownExternal = (varName) => {
|
|
689
|
+
for (const prefix of knownExternalVars) {
|
|
690
|
+
if (varName.startsWith(prefix))
|
|
691
|
+
return true;
|
|
692
|
+
}
|
|
693
|
+
return false;
|
|
694
|
+
};
|
|
695
|
+
for (const file of files) {
|
|
696
|
+
const content = fs.readFileSync(file, "utf8");
|
|
697
|
+
const lines = content.split("\n");
|
|
698
|
+
// Track locally defined CSS variables (inline definitions like ['--var-name' as any]: 'value' or ["--var-name" as any]: 'value')
|
|
699
|
+
const locallyDefinedVars = new Set();
|
|
700
|
+
Array.from(content.matchAll(/\[["'](--[a-zA-Z0-9-]+)["']\s*as\s*any\]/g)).forEach((m) => {
|
|
701
|
+
const varName = m[1];
|
|
702
|
+
if (varName)
|
|
703
|
+
locallyDefinedVars.add(varName);
|
|
704
|
+
});
|
|
705
|
+
lines.forEach((line, index) => {
|
|
706
|
+
if (line.trim().startsWith("//") || line.trim().startsWith("/*"))
|
|
707
|
+
return;
|
|
708
|
+
// Find all var(--*) references - capture full match to check for fallbacks
|
|
709
|
+
const varRefs = line.matchAll(/var\((--[a-zA-Z0-9-]+)(,\s*[^)]+)?\)/g);
|
|
710
|
+
for (const match of varRefs) {
|
|
711
|
+
const varName = match[1];
|
|
712
|
+
const hasFallback = !!match[2]; // Has a fallback value like ", #fff"
|
|
713
|
+
// Skip known external variables
|
|
714
|
+
if (isKnownExternal(varName))
|
|
715
|
+
continue;
|
|
716
|
+
// Skip locally defined variables (inline CSS custom properties)
|
|
717
|
+
if (locallyDefinedVars.has(varName))
|
|
718
|
+
continue;
|
|
719
|
+
// Check if variable is defined
|
|
720
|
+
if (!definedVars.has(varName)) {
|
|
721
|
+
// Variables with fallbacks are warnings (they won't break), without are errors
|
|
722
|
+
issues.push({
|
|
723
|
+
file,
|
|
724
|
+
line: index + 1,
|
|
725
|
+
type: "undefined-css-var",
|
|
726
|
+
severity: hasFallback ? "warning" : "error",
|
|
727
|
+
message: `Undefined CSS variable: ${varName}${hasFallback ? " (has fallback)" : ""}`,
|
|
728
|
+
suggestion: hasFallback
|
|
729
|
+
? `Consider adding ${varName} to app/tokens.css for consistency`
|
|
730
|
+
: `Add ${varName} to app/tokens.css or use an existing token`,
|
|
731
|
+
snippet: line.trim().substring(0, 80),
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
const errorCount = issues.filter((i) => i.severity === "error").length;
|
|
738
|
+
const warningCount = issues.filter((i) => i.severity === "warning").length;
|
|
739
|
+
return {
|
|
740
|
+
name: `Undefined CSS Variables (${errorCount} errors, ${warningCount} warnings)`,
|
|
741
|
+
passed: errorCount === 0,
|
|
742
|
+
blocking: true,
|
|
743
|
+
issues,
|
|
744
|
+
duration: Date.now() - startTime,
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Header Icon Button Uniformity - ensures top-nav (cart/notifications/wishlist) icon triggers
|
|
749
|
+
* use the standard glass hover token and have an active/open background state.
|
|
750
|
+
*
|
|
751
|
+
* Why: A wrong token (e.g. --glass-bg-light) can silently render as transparent, creating
|
|
752
|
+
* a "no background" regression that is easy to miss visually.
|
|
753
|
+
*
|
|
754
|
+
* Files that delegate to HeaderIconButton (which contains the required tokens) are considered
|
|
755
|
+
* compliant if they pass isActive={isOpen} to the shared component.
|
|
756
|
+
*/
|
|
757
|
+
async checkHeaderIconButtonUniformity() {
|
|
758
|
+
const startTime = Date.now();
|
|
759
|
+
const issues = [];
|
|
760
|
+
const targets = [
|
|
761
|
+
{
|
|
762
|
+
file: "components/cart/CartDrawer.tsx",
|
|
763
|
+
required: {
|
|
764
|
+
hoverToken: "hover:bg-[var(--glass-hover-light)]",
|
|
765
|
+
activeToken: "bg-[var(--glass-hover-light)]",
|
|
766
|
+
disallowedVar: "--glass-bg-light",
|
|
767
|
+
requiresIsOpenActive: true,
|
|
768
|
+
},
|
|
769
|
+
},
|
|
770
|
+
{
|
|
771
|
+
file: "components/cart/WishlistDrawer.tsx",
|
|
772
|
+
required: {
|
|
773
|
+
hoverToken: "hover:bg-[var(--glass-hover-light)]",
|
|
774
|
+
activeToken: "bg-[var(--glass-hover-light)]",
|
|
775
|
+
disallowedVar: "--glass-bg-light",
|
|
776
|
+
requiresIsOpenActive: true,
|
|
777
|
+
},
|
|
778
|
+
},
|
|
779
|
+
{
|
|
780
|
+
file: "components/notifications/NotificationBellButton.tsx",
|
|
781
|
+
required: {
|
|
782
|
+
hoverToken: "hover:bg-[var(--glass-hover-light)]",
|
|
783
|
+
activeToken: "bg-[var(--glass-hover-light)]",
|
|
784
|
+
disallowedVar: "--glass-bg-light",
|
|
785
|
+
requiresIsOpenActive: false,
|
|
786
|
+
// NotificationBellButton delegates to HeaderIconButton, so it doesn't need the tokens directly
|
|
787
|
+
allowsDelegation: true,
|
|
788
|
+
},
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
file: "components/navigation/NotificationsBell.tsx",
|
|
792
|
+
required: {
|
|
793
|
+
disallowedVar: "--glass-bg-light",
|
|
794
|
+
requiresIsOpenActive: false,
|
|
795
|
+
},
|
|
796
|
+
},
|
|
797
|
+
];
|
|
798
|
+
const workspaceRoot = process.cwd();
|
|
799
|
+
const pushIssue = (file, message, suggestion) => {
|
|
800
|
+
issues.push({
|
|
801
|
+
file,
|
|
802
|
+
line: 1,
|
|
803
|
+
type: "header-icon-uniformity",
|
|
804
|
+
severity: "error",
|
|
805
|
+
message,
|
|
806
|
+
suggestion,
|
|
807
|
+
});
|
|
808
|
+
};
|
|
809
|
+
// Check if HeaderIconButton has the required tokens (it's the source of truth)
|
|
810
|
+
const headerIconButtonPath = path.join(workspaceRoot, "components/navigation/HeaderIconButton.tsx");
|
|
811
|
+
let headerIconButtonHasTokens = false;
|
|
812
|
+
if (fs.existsSync(headerIconButtonPath)) {
|
|
813
|
+
const headerIconContent = fs.readFileSync(headerIconButtonPath, "utf8");
|
|
814
|
+
headerIconButtonHasTokens =
|
|
815
|
+
headerIconContent.includes("hover:bg-[var(--glass-hover-light)]") &&
|
|
816
|
+
headerIconContent.includes("bg-[var(--glass-hover-light)]") &&
|
|
817
|
+
headerIconContent.includes("isActive");
|
|
818
|
+
}
|
|
819
|
+
for (const t of targets) {
|
|
820
|
+
const absolute = path.join(workspaceRoot, t.file);
|
|
821
|
+
if (!fs.existsSync(absolute)) {
|
|
822
|
+
pushIssue(t.file, "Expected header icon file is missing", "Restore or update the preflight target list");
|
|
823
|
+
continue;
|
|
824
|
+
}
|
|
825
|
+
const content = fs.readFileSync(absolute, "utf8");
|
|
826
|
+
// Check if file delegates to HeaderIconButton with proper isActive handling
|
|
827
|
+
const delegatesToHeaderIconButton = content.includes("HeaderIconButton") &&
|
|
828
|
+
(content.includes("isActive={isOpen}") || content.includes("isActive={"));
|
|
829
|
+
if (t.required.disallowedVar && content.includes(t.required.disallowedVar)) {
|
|
830
|
+
pushIssue(t.file, `Disallowed/legacy CSS variable found: ${t.required.disallowedVar}`, "Use --glass-hover-light for header icon button hover/active backgrounds");
|
|
831
|
+
}
|
|
832
|
+
// If delegating to HeaderIconButton with isActive, skip token checks (HeaderIconButton has them)
|
|
833
|
+
// Also skip if allowsDelegation is set and file uses HeaderIconButton
|
|
834
|
+
if ((delegatesToHeaderIconButton && headerIconButtonHasTokens) ||
|
|
835
|
+
(t.required.allowsDelegation && content.includes("HeaderIconButton"))) {
|
|
836
|
+
continue;
|
|
837
|
+
}
|
|
838
|
+
if (t.required.hoverToken && !content.includes(t.required.hoverToken)) {
|
|
839
|
+
pushIssue(t.file, `Missing required header icon hover background token: ${t.required.hoverToken}`, "Ensure IconButton className includes the standard glass hover token");
|
|
840
|
+
}
|
|
841
|
+
if (t.required.activeToken && !content.includes(t.required.activeToken)) {
|
|
842
|
+
pushIssue(t.file, `Missing required header icon active background token: ${t.required.activeToken}`, "When a drawer/popup is open, keep the icon background visible for context");
|
|
843
|
+
}
|
|
844
|
+
if (t.required.requiresIsOpenActive) {
|
|
845
|
+
const hasIsOpenActive = /\bisOpen\b/.test(content) &&
|
|
846
|
+
(/\bisOpen\s*\?[^\n]*bg-\[var\(--glass-hover-light\)\]/.test(content) ||
|
|
847
|
+
/\bisOpen\s*&&[^\n]*bg-\[var\(--glass-hover-light\)\]/.test(content));
|
|
848
|
+
if (!hasIsOpenActive) {
|
|
849
|
+
pushIssue(t.file, "Header icon button must reflect open state (isOpen) with a persistent background", "Add an isOpen conditional class that applies bg-[var(--glass-hover-light)]");
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
// Notification button should accept isActive, and the wrapper should pass it when open.
|
|
854
|
+
const bellButtonFile = path.join(workspaceRoot, "components/notifications/NotificationBellButton.tsx");
|
|
855
|
+
if (fs.existsSync(bellButtonFile)) {
|
|
856
|
+
const bellButton = fs.readFileSync(bellButtonFile, "utf8");
|
|
857
|
+
// Check for isActive prop - can be defined as isActive?: boolean or isActive: boolean or in interface
|
|
858
|
+
const hasIsActiveProp = /isActive\s*\??\s*:\s*boolean/.test(bellButton) ||
|
|
859
|
+
/interface[^{]*\{[^}]*isActive/.test(bellButton);
|
|
860
|
+
if (!hasIsActiveProp) {
|
|
861
|
+
pushIssue("components/notifications/NotificationBellButton.tsx", "NotificationBellButton must support an isActive prop for header uniformity", "Add `isActive?: boolean` and apply bg-[var(--glass-hover-light)] when active");
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
const bellWrapperFile = path.join(workspaceRoot, "components/navigation/NotificationsBell.tsx");
|
|
865
|
+
if (fs.existsSync(bellWrapperFile)) {
|
|
866
|
+
const bellWrapper = fs.readFileSync(bellWrapperFile, "utf8");
|
|
867
|
+
if (!/NotificationBellButton[\s\S]*isActive=\{isOpen\}/.test(bellWrapper)) {
|
|
868
|
+
pushIssue("components/navigation/NotificationsBell.tsx", "NotificationsBell must pass isOpen into NotificationBellButton (isActive)", "Pass `isActive={isOpen}` to keep the header icon background visible while open");
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
872
|
+
return {
|
|
873
|
+
name: `Header Icon Button Uniformity (${issues.length} issues)`,
|
|
874
|
+
passed: !hasErrors,
|
|
875
|
+
blocking: true,
|
|
876
|
+
issues,
|
|
877
|
+
duration: Date.now() - startTime,
|
|
878
|
+
};
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Z-Index Enforcement - ensures z-index tokens are used
|
|
882
|
+
*
|
|
883
|
+
* Exceptions:
|
|
884
|
+
* - None for Tailwind z-* classes: steering forbids Tailwind z-index utilities entirely.
|
|
885
|
+
* - var(--z-*) (already using tokens)
|
|
886
|
+
*/
|
|
887
|
+
async checkZIndex() {
|
|
888
|
+
const startTime = Date.now();
|
|
889
|
+
const issues = [];
|
|
890
|
+
const files = await getAppComponentsTsxFiles();
|
|
891
|
+
for (const file of files) {
|
|
892
|
+
const content = fs.readFileSync(file, "utf8");
|
|
893
|
+
const lines = content.split("\n");
|
|
894
|
+
lines.forEach((line, index) => {
|
|
895
|
+
if (line.trim().startsWith("//"))
|
|
896
|
+
return;
|
|
897
|
+
// Skip lines that already use CSS variables
|
|
898
|
+
if (line.includes("var(--z-"))
|
|
899
|
+
return;
|
|
900
|
+
// Tailwind z-index classes are forbidden (steering rule 11b).
|
|
901
|
+
// Catch prefixed variants: md:z-50, hover:z-10, data-[state=open]:z-50, etc.
|
|
902
|
+
// Also catch arbitrary values: z-[999], -z-[1].
|
|
903
|
+
const tailwindZIndexPatterns = [
|
|
904
|
+
/\b(?:[a-z0-9_\-\[\]=]+:)*-?z-(\d+)\b/g, // z-10, md:z-50, hover:z-10
|
|
905
|
+
/\b(?:[a-z0-9_\-\[\]=]+:)*-?z-\[[^\]]+\]/g, // z-[999], sm:z-[var(--z-modal)]
|
|
906
|
+
];
|
|
907
|
+
for (const pattern of tailwindZIndexPatterns) {
|
|
908
|
+
pattern.lastIndex = 0;
|
|
909
|
+
let match;
|
|
910
|
+
while ((match = pattern.exec(line)) !== null) {
|
|
911
|
+
const value = match[0];
|
|
912
|
+
issues.push({
|
|
913
|
+
file,
|
|
914
|
+
line: index + 1,
|
|
915
|
+
type: "tailwind-zindex",
|
|
916
|
+
severity: this.strictUniformity ? "error" : "warning",
|
|
917
|
+
message: `Tailwind z-index utility is forbidden: ${value}`,
|
|
918
|
+
suggestion: 'Use style={{ zIndex: "var(--z-*)" }} with the appropriate z-index token instead',
|
|
919
|
+
snippet: line.trim().substring(0, 120),
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
// Hardcoded z-index > 10
|
|
924
|
+
const zMatch = line.match(/zIndex:\s*(\d+)/);
|
|
925
|
+
if (zMatch && parseInt(zMatch[1]) > 10) {
|
|
926
|
+
issues.push({
|
|
927
|
+
file,
|
|
928
|
+
line: index + 1,
|
|
929
|
+
type: "hardcoded-zindex",
|
|
930
|
+
severity: "warning",
|
|
931
|
+
message: `Hardcoded zIndex: ${zMatch[1]}`,
|
|
932
|
+
suggestion: "Use var(--z-content-overlay|dropdown|modal|tooltip|toast)",
|
|
933
|
+
snippet: line.trim().substring(0, 80),
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
939
|
+
return {
|
|
940
|
+
name: "Z-Index Enforcement",
|
|
941
|
+
passed: !hasErrors,
|
|
942
|
+
blocking: this.strictUniformity,
|
|
943
|
+
issues,
|
|
944
|
+
duration: Date.now() - startTime,
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Toast Polish - ensures unified toast uses spacing tokens (prevents “text touching border” regressions).
|
|
949
|
+
*/
|
|
950
|
+
async checkToastPolish() {
|
|
951
|
+
const startTime = Date.now();
|
|
952
|
+
const issues = [];
|
|
953
|
+
const toastStatusPath = "components/shared/status/variants/ToastStatus.tsx";
|
|
954
|
+
if (!fs.existsSync(toastStatusPath)) {
|
|
955
|
+
return {
|
|
956
|
+
name: "Toast Polish",
|
|
957
|
+
passed: true,
|
|
958
|
+
blocking: true,
|
|
959
|
+
issues,
|
|
960
|
+
duration: Date.now() - startTime,
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
const content = fs.readFileSync(toastStatusPath, "utf8");
|
|
964
|
+
if (!content.includes("var(--toast-padding)")) {
|
|
965
|
+
issues.push({
|
|
966
|
+
file: toastStatusPath,
|
|
967
|
+
line: 1,
|
|
968
|
+
type: "toast-missing-padding-token",
|
|
969
|
+
severity: "error",
|
|
970
|
+
message: "Unified toast must use var(--toast-padding) for consistent inner spacing",
|
|
971
|
+
suggestion: 'Add style={{ padding: "var(--toast-padding)" }} (or equivalent) in ToastStatus',
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
975
|
+
return {
|
|
976
|
+
name: "Toast Polish",
|
|
977
|
+
passed: !hasErrors,
|
|
978
|
+
blocking: true,
|
|
979
|
+
issues,
|
|
980
|
+
duration: Date.now() - startTime,
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* CardContent Padding - ensures CardContent supports responsive padding utilities.
|
|
985
|
+
*
|
|
986
|
+
* We intentionally keep the default padding as a Tailwind class (e.g. "p-4")
|
|
987
|
+
* instead of inline styles, so consumers can override via className (md:p-8, etc).
|
|
988
|
+
*/
|
|
989
|
+
async checkCardContentPadding() {
|
|
990
|
+
const startTime = Date.now();
|
|
991
|
+
const issues = [];
|
|
992
|
+
const cardPath = "packages/ui/src/components/layout/Card.tsx";
|
|
993
|
+
if (!fs.existsSync(cardPath)) {
|
|
994
|
+
return {
|
|
995
|
+
name: "CardContent Padding",
|
|
996
|
+
passed: true,
|
|
997
|
+
blocking: true,
|
|
998
|
+
issues,
|
|
999
|
+
duration: Date.now() - startTime,
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
const content = fs.readFileSync(cardPath, "utf8");
|
|
1003
|
+
const hasClassBasedPadding = content.includes('className={cn("p-4"');
|
|
1004
|
+
if (!hasClassBasedPadding) {
|
|
1005
|
+
issues.push({
|
|
1006
|
+
file: cardPath,
|
|
1007
|
+
line: 1,
|
|
1008
|
+
type: "cardcontent-padding-not-class-based",
|
|
1009
|
+
severity: "error",
|
|
1010
|
+
message: 'CardContent must include default "p-4" via className (not inline padding) to allow responsive overrides',
|
|
1011
|
+
suggestion: 'Set className={cn("p-4", className)} and avoid forcing padding via inline style',
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
1015
|
+
return {
|
|
1016
|
+
name: "CardContent Padding",
|
|
1017
|
+
passed: !hasErrors,
|
|
1018
|
+
blocking: true,
|
|
1019
|
+
issues,
|
|
1020
|
+
duration: Date.now() - startTime,
|
|
1021
|
+
};
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Product Page Polish - detects common "no gap around card" and overlay spacing regressions.
|
|
1025
|
+
*
|
|
1026
|
+
* Scope intentionally limited to product pages/components to reduce false positives.
|
|
1027
|
+
*/
|
|
1028
|
+
async checkProductPagePolish() {
|
|
1029
|
+
const startTime = Date.now();
|
|
1030
|
+
const issues = [];
|
|
1031
|
+
const files = await file_cache_1.fileCache.getFiles("{app/product,components/product,components/gallery}/**/*.{tsx,jsx}", {
|
|
1032
|
+
ignore: EXCLUDED,
|
|
1033
|
+
});
|
|
1034
|
+
const hasAnyPadding = (block) => {
|
|
1035
|
+
// padding via inline style
|
|
1036
|
+
if (/\bpadding\s*:\s*[^,}]+/m.test(block))
|
|
1037
|
+
return true;
|
|
1038
|
+
// padding via tailwind class utilities (works for quoted strings AND template literals)
|
|
1039
|
+
if (/\b(?:p|px|py|pt|pb|pl|pr)-(?:\d+|\[[^\]]+\])\b/.test(block))
|
|
1040
|
+
return true;
|
|
1041
|
+
// padding via sx prop (allowed only in UI package, but can appear in some legacy components)
|
|
1042
|
+
if (/\bsx=\{\{[\s\S]*?\b(?:p|px|py|pt|pb|pl|pr)\s*:\s*[^,}]+/m.test(block))
|
|
1043
|
+
return true;
|
|
1044
|
+
return false;
|
|
1045
|
+
};
|
|
1046
|
+
for (const file of files) {
|
|
1047
|
+
const content = fs.readFileSync(file, "utf8");
|
|
1048
|
+
const lines = content.split("\n");
|
|
1049
|
+
// 0) Back-to-back Cards should have explicit vertical spacing.
|
|
1050
|
+
// This is a lightweight regression guard for "cards touching" on product pages.
|
|
1051
|
+
for (let i = 0; i < lines.length - 1; i++) {
|
|
1052
|
+
const line = lines[i];
|
|
1053
|
+
if (line.trim().startsWith("//"))
|
|
1054
|
+
continue;
|
|
1055
|
+
// Check for preflight-ignore in surrounding lines (5 lines before and 3 after)
|
|
1056
|
+
const contextLines = lines
|
|
1057
|
+
.slice(Math.max(0, i - 5), Math.min(lines.length, i + 3))
|
|
1058
|
+
.join("\n");
|
|
1059
|
+
if (contextLines.includes("preflight-ignore"))
|
|
1060
|
+
continue;
|
|
1061
|
+
const isCardClose = /<\s*\/\s*Card\s*>/.test(line);
|
|
1062
|
+
if (!isCardClose)
|
|
1063
|
+
continue;
|
|
1064
|
+
// Look ahead a few lines for the next Card open.
|
|
1065
|
+
const lookahead = lines.slice(i + 1, Math.min(i + 6, lines.length)).join("\n");
|
|
1066
|
+
const nextCardLineIndex = lines
|
|
1067
|
+
.slice(i + 1, Math.min(i + 6, lines.length))
|
|
1068
|
+
.findIndex((l) => /<\s*Card\b/.test(l));
|
|
1069
|
+
if (nextCardLineIndex === -1)
|
|
1070
|
+
continue;
|
|
1071
|
+
const nextCardLine = lines[i + 1 + nextCardLineIndex];
|
|
1072
|
+
const hasExplicitSpacing = /\b(?:mt|my)-(?:\d+|\[[^\]]+\])\b/.test(nextCardLine) ||
|
|
1073
|
+
/marginTop\s*:\s*[^,}]+/.test(lookahead) ||
|
|
1074
|
+
/\bclassName=\{?[^\n]*\b(?:mt|my)-(?:\d+|\[[^\]]+\])\b/.test(lookahead);
|
|
1075
|
+
// Skip obvious grid/gap contexts (spacing is handled by parent layouts).
|
|
1076
|
+
const likelyInGridOrGap = /\b(?:grid|gap-|space-y-)\b/.test(lookahead);
|
|
1077
|
+
if (!likelyInGridOrGap && !hasExplicitSpacing) {
|
|
1078
|
+
issues.push({
|
|
1079
|
+
file,
|
|
1080
|
+
line: i + 2 + nextCardLineIndex,
|
|
1081
|
+
type: "card-no-vertical-gap",
|
|
1082
|
+
severity: this.strictUniformity ? "error" : "warning",
|
|
1083
|
+
message: "Back-to-back <Card> blocks appear without explicit vertical spacing (cards may touch)",
|
|
1084
|
+
suggestion: "Add vertical spacing via className (mt-*/my-*) or wrap Cards in a Stack with spacing={3}",
|
|
1085
|
+
snippet: nextCardLine.trim().substring(0, 140),
|
|
1086
|
+
});
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1090
|
+
const line = lines[i];
|
|
1091
|
+
if (line.trim().startsWith("//"))
|
|
1092
|
+
continue;
|
|
1093
|
+
// Check for preflight-ignore in surrounding lines (3 lines before and after)
|
|
1094
|
+
const contextLines = lines
|
|
1095
|
+
.slice(Math.max(0, i - 5), Math.min(lines.length, i + 3))
|
|
1096
|
+
.join("\n");
|
|
1097
|
+
if (contextLines.includes("preflight-ignore"))
|
|
1098
|
+
continue;
|
|
1099
|
+
// 1) Bordered containers should have padding.
|
|
1100
|
+
// Heuristic focuses on full borders (not border-b/t/l/r/x/y) and avoids false positives from "--border-color".
|
|
1101
|
+
const looksLikeContainerStart = /<\s*(Box|div|section|article|aside|Card)\b/.test(line);
|
|
1102
|
+
const block = lines.slice(i, Math.min(i + 10, lines.length)).join("\n");
|
|
1103
|
+
const extendedBlock = lines.slice(i, Math.min(i + 40, lines.length)).join("\n");
|
|
1104
|
+
const hasFullBorder = /border\s*:\s*`?1px\s+solid/.test(block) ||
|
|
1105
|
+
/(^|["'\s])border(\s|["'])/m.test(block) ||
|
|
1106
|
+
/(^|["'\s])border-(?!b\b|t\b|l\b|r\b|x\b|y\b|color\b)[^\s"']+/m.test(block);
|
|
1107
|
+
const hasVisualSurface = /\bshadow\b|bg-\w|backdrop-blur|rounded-\[|\brounded\b/.test(block);
|
|
1108
|
+
const hasTypography = block.includes("<Typography");
|
|
1109
|
+
const looksLikeTinyIndicator = !hasTypography && /\bw-(1|2|3|4|5|6)\b/.test(block) && /\bh-(1|2|3|4|5|6)\b/.test(block);
|
|
1110
|
+
const looksLikeImageWrapper = /<Image\b|component=\{?['"]img['"]\}?|\bsrc=\{?|backgroundImage\s*:|objectFit\s*:|bg-contain\b|bg-cover\b|object-contain\b|object-cover\b/.test(extendedBlock);
|
|
1111
|
+
if (looksLikeContainerStart &&
|
|
1112
|
+
hasFullBorder &&
|
|
1113
|
+
hasVisualSurface &&
|
|
1114
|
+
!looksLikeTinyIndicator &&
|
|
1115
|
+
!looksLikeImageWrapper) {
|
|
1116
|
+
if (!hasAnyPadding(block)) {
|
|
1117
|
+
issues.push({
|
|
1118
|
+
file,
|
|
1119
|
+
line: i + 1,
|
|
1120
|
+
type: "bordered-container-no-padding",
|
|
1121
|
+
severity: this.strictUniformity ? "error" : "warning",
|
|
1122
|
+
message: "Bordered UI container appears to have no padding (content may touch the border)",
|
|
1123
|
+
suggestion: 'Add padding via className (p-*, px-*/py-*) or style={{ padding: "var(--spacing-*)" }}',
|
|
1124
|
+
snippet: line.trim().substring(0, 140),
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
// 2) Overlay text pills (e.g., "Click to zoom") should have explicit padding.
|
|
1129
|
+
// Avoid false positives on IconButton/Button that reference overlay tokens for hover states.
|
|
1130
|
+
const tagMatch = line.match(/<\s*([A-Za-z0-9_]+)/);
|
|
1131
|
+
const tagName = tagMatch?.[1] ?? "";
|
|
1132
|
+
const looksLikeOverlay = /\babsolute\b/.test(line) &&
|
|
1133
|
+
(line.includes("Click to zoom") ||
|
|
1134
|
+
line.includes("rgba(0, 0, 0") ||
|
|
1135
|
+
line.includes("overlay-backdrop")) &&
|
|
1136
|
+
tagName !== "IconButton" &&
|
|
1137
|
+
tagName !== "Button";
|
|
1138
|
+
if (looksLikeOverlay) {
|
|
1139
|
+
const block = lines.slice(i, Math.min(i + 12, lines.length)).join("\n");
|
|
1140
|
+
const hasOverlayBg = block.includes("var(--overlay-backdrop)") ||
|
|
1141
|
+
/rgba\(\s*0\s*,\s*0\s*,\s*0\s*,\s*0\.[0-9]+\s*\)/.test(block);
|
|
1142
|
+
// Only treat as a "pill" if it looks like a compact label.
|
|
1143
|
+
const looksLikePillText = block.includes("Click to zoom") ||
|
|
1144
|
+
(/\btext-(xs|sm)\b/.test(block) && /\brounded\b|rounded-\[/.test(block));
|
|
1145
|
+
if (hasOverlayBg && looksLikePillText && !hasAnyPadding(block)) {
|
|
1146
|
+
issues.push({
|
|
1147
|
+
file,
|
|
1148
|
+
line: i + 1,
|
|
1149
|
+
type: "overlay-no-padding",
|
|
1150
|
+
severity: this.strictUniformity ? "error" : "warning",
|
|
1151
|
+
message: "Overlay label appears to have no padding (text may look cramped on dark backdrop)",
|
|
1152
|
+
suggestion: 'Add padding via className (px-*/py-*) or style={{ padding: "var(--spacing-*)" }}',
|
|
1153
|
+
snippet: line.trim().substring(0, 140),
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
const hasErrors = issues.some((i) => i.severity === "error");
|
|
1160
|
+
return {
|
|
1161
|
+
name: "Product Page Polish",
|
|
1162
|
+
passed: !hasErrors,
|
|
1163
|
+
blocking: this.strictUniformity,
|
|
1164
|
+
issues,
|
|
1165
|
+
duration: Date.now() - startTime,
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Global UI Polish (non-blocking) - broader scan for common spacing regressions.
|
|
1170
|
+
*
|
|
1171
|
+
* This is intentionally WARNING-only to keep preflights useful without becoming
|
|
1172
|
+
* deployment-blocking due to heuristic false positives.
|
|
1173
|
+
*/
|
|
1174
|
+
async checkGlobalPolish() {
|
|
1175
|
+
const startTime = Date.now();
|
|
1176
|
+
const issues = [];
|
|
1177
|
+
const files = await file_cache_1.fileCache.getAppAndComponentsTSX();
|
|
1178
|
+
const hasAnyPadding = (block) => {
|
|
1179
|
+
if (/\bpadding\s*:\s*[^,}]+/m.test(block))
|
|
1180
|
+
return true;
|
|
1181
|
+
if (/\b(?:p|px|py|pt|pb|pl|pr)-(?:\d+|\[[^\]]+\])\b/.test(block))
|
|
1182
|
+
return true;
|
|
1183
|
+
if (/\bsx=\{\{[\s\S]*?\b(?:p|px|py|pt|pb|pl|pr)\s*:\s*[^,}]+/m.test(block))
|
|
1184
|
+
return true;
|
|
1185
|
+
return false;
|
|
1186
|
+
};
|
|
1187
|
+
for (const file of files) {
|
|
1188
|
+
const content = fs.readFileSync(file, "utf8");
|
|
1189
|
+
const lines = content.split("\n");
|
|
1190
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1191
|
+
const line = lines[i];
|
|
1192
|
+
if (line.trim().startsWith("//"))
|
|
1193
|
+
continue;
|
|
1194
|
+
// Check for preflight-ignore in surrounding lines (15 lines before and 3 after)
|
|
1195
|
+
const contextLines = lines
|
|
1196
|
+
.slice(Math.max(0, i - 15), Math.min(lines.length, i + 3))
|
|
1197
|
+
.join("\n");
|
|
1198
|
+
if (contextLines.includes("preflight-ignore"))
|
|
1199
|
+
continue;
|
|
1200
|
+
// Heuristic A: bordered surface containers should have padding.
|
|
1201
|
+
// Full border only; avoid false positives from "--border-color" and one-sided borders.
|
|
1202
|
+
const looksLikeContainerStart = /<\s*(Box|div|section|article|aside|Card)\b/.test(line);
|
|
1203
|
+
const block = lines.slice(i, Math.min(i + 10, lines.length)).join("\n");
|
|
1204
|
+
const extendedBlock = lines.slice(i, Math.min(i + 40, lines.length)).join("\n");
|
|
1205
|
+
const hasFullBorder = /border\s*:\s*`?1px\s+solid/.test(block) ||
|
|
1206
|
+
/(^|["'\s])border(\s|["'])/m.test(block) ||
|
|
1207
|
+
/(^|["'\s])border-(?!b\b|t\b|l\b|r\b|x\b|y\b|color\b)[^\s"']+/m.test(block);
|
|
1208
|
+
// Only flag text-bearing surfaces; skip pure image/layout wrappers.
|
|
1209
|
+
const hasTypography = block.includes("<Typography");
|
|
1210
|
+
const hasSurfaceStyling = /\bshadow\b|bg-\w|backdrop-blur/.test(block);
|
|
1211
|
+
const looksLikeTinyIndicator = /\bw-(4|5|6)\b/.test(block) &&
|
|
1212
|
+
/\bh-(4|5|6)\b/.test(block) &&
|
|
1213
|
+
/\bborder-(2|\[)/.test(block) &&
|
|
1214
|
+
!/\bbg-\w/.test(block) &&
|
|
1215
|
+
!/\bshadow\b/.test(block);
|
|
1216
|
+
const looksLikeImageWrapper = /<Image\b|component=\{?['"]img['"]\}?|\bsrc=\{?|backgroundImage\s*:|objectFit\s*:|bg-contain\b|bg-cover\b|object-contain\b|object-cover\b/.test(block);
|
|
1217
|
+
const looksLikeSmallCenteredBadge = /\bflex\b/.test(block) &&
|
|
1218
|
+
/\bitems-center\b/.test(block) &&
|
|
1219
|
+
/\bjustify-center\b/.test(block) &&
|
|
1220
|
+
/width\s*:\s*['"]?(?:1\d|2[0-4])px['"]?/.test(block) &&
|
|
1221
|
+
/height\s*:\s*['"]?(?:1\d|2[0-4])px['"]?/.test(block);
|
|
1222
|
+
const looksLikeBorderedMediaFrame = block.includes("overflow-hidden") &&
|
|
1223
|
+
/\bborder-(2|\[)/.test(block) &&
|
|
1224
|
+
(/(\bw-\d+\b)/.test(block) || /(\bh-\d+\b)/.test(block)) &&
|
|
1225
|
+
/(object-contain|object-cover|component=\{?['"]img['"]\}?|<Image\b)/.test(extendedBlock);
|
|
1226
|
+
if (looksLikeContainerStart &&
|
|
1227
|
+
hasFullBorder &&
|
|
1228
|
+
hasSurfaceStyling &&
|
|
1229
|
+
hasTypography &&
|
|
1230
|
+
!looksLikeTinyIndicator &&
|
|
1231
|
+
!looksLikeSmallCenteredBadge &&
|
|
1232
|
+
!looksLikeImageWrapper &&
|
|
1233
|
+
!looksLikeBorderedMediaFrame) {
|
|
1234
|
+
if (!hasAnyPadding(block)) {
|
|
1235
|
+
issues.push({
|
|
1236
|
+
file,
|
|
1237
|
+
line: i + 1,
|
|
1238
|
+
type: "bordered-container-no-padding",
|
|
1239
|
+
severity: "warning",
|
|
1240
|
+
message: "Bordered UI container appears to have no padding (content may touch the border)",
|
|
1241
|
+
suggestion: 'Add padding via className (p-*, px-*/py-*) or style={{ padding: "var(--spacing-*)" }}',
|
|
1242
|
+
snippet: line.trim().substring(0, 140),
|
|
1243
|
+
});
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
// Heuristic B: overlay text pills (absolute + dark backdrop) should have padding.
|
|
1247
|
+
const tagMatch = line.match(/<\s*([A-Za-z0-9_]+)/);
|
|
1248
|
+
const tagName = tagMatch?.[1] ?? "";
|
|
1249
|
+
const looksLikeOverlay = /\babsolute\b/.test(line) &&
|
|
1250
|
+
(line.includes("var(--overlay-backdrop)") || line.includes("rgba(0, 0, 0")) &&
|
|
1251
|
+
tagName !== "IconButton" &&
|
|
1252
|
+
tagName !== "Button";
|
|
1253
|
+
if (looksLikeOverlay) {
|
|
1254
|
+
const block = lines.slice(i, Math.min(i + 12, lines.length)).join("\n");
|
|
1255
|
+
const hasOverlayBg = block.includes("var(--overlay-backdrop)") ||
|
|
1256
|
+
/rgba\(\s*0\s*,\s*0\s*,\s*0\s*,\s*0\.[0-9]+\s*\)/.test(block);
|
|
1257
|
+
const looksLikePillText = /\btext-(xs|sm)\b/.test(block) && /\brounded\b|rounded-\[/.test(block);
|
|
1258
|
+
if (hasOverlayBg && looksLikePillText && !hasAnyPadding(block)) {
|
|
1259
|
+
issues.push({
|
|
1260
|
+
file,
|
|
1261
|
+
line: i + 1,
|
|
1262
|
+
type: "overlay-no-padding",
|
|
1263
|
+
severity: "warning",
|
|
1264
|
+
message: "Overlay label appears to have no padding (text may look cramped on dark backdrop)",
|
|
1265
|
+
suggestion: 'Add padding via className (px-*/py-*) or style={{ padding: "var(--spacing-*)" }}',
|
|
1266
|
+
snippet: line.trim().substring(0, 140),
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
// Heuristic C: button-like controls should not explicitly zero out padding.
|
|
1271
|
+
// This catches common regressions like "text flush to border" when someone
|
|
1272
|
+
// adds px-0 / p-0 or style padding: 0 to a CTA.
|
|
1273
|
+
const looksLikeButtonTag = /<\s*(Button|button|a)\b/.test(line);
|
|
1274
|
+
if (looksLikeButtonTag) {
|
|
1275
|
+
const block = lines.slice(i, Math.min(i + 14, lines.length)).join("\n");
|
|
1276
|
+
const hasZeroPaddingClass = /\b(?:p|px|py|pt|pb|pl|pr)-0\b/.test(block);
|
|
1277
|
+
const hasZeroPaddingStyle = /\bpadding(?:Left|Right|Top|Bottom)?\s*:\s*(?:0|"0"|'0'|"0px"|'0px')\b/.test(block);
|
|
1278
|
+
// Reduce noise: require CTA-ish copy nearby.
|
|
1279
|
+
const hasCtaCopy = /(\bAdd to Cart\b|\bCheckout\b|\bBuy\b|\bSell\b|\bContinue\b|\bSave\b|\bSubmit\b)/i.test(block);
|
|
1280
|
+
const hasButtonLikeClasses = /\bbg-\[|\bbg-[a-z0-9-]+\b|\bborder\b|\bborder-[a-z0-9-]+\b|\brounded\b/.test(block);
|
|
1281
|
+
if ((hasZeroPaddingClass || hasZeroPaddingStyle) &&
|
|
1282
|
+
(hasCtaCopy || hasButtonLikeClasses)) {
|
|
1283
|
+
issues.push({
|
|
1284
|
+
file,
|
|
1285
|
+
line: i + 1,
|
|
1286
|
+
type: "button-zero-padding",
|
|
1287
|
+
severity: this.strictUniformity ? "error" : "warning",
|
|
1288
|
+
message: "Button-like control appears to remove padding (can cause text to touch the border)",
|
|
1289
|
+
suggestion: "Remove p-0/px-0/py-0 or use spacing tokens (e.g., px-4 py-2) / var(--spacing-*)",
|
|
1290
|
+
snippet: line.trim().substring(0, 140),
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
return {
|
|
1297
|
+
name: `Global UI Polish (${issues.length} warnings)`,
|
|
1298
|
+
passed: true,
|
|
1299
|
+
blocking: true,
|
|
1300
|
+
issues,
|
|
1301
|
+
duration: Date.now() - startTime,
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1304
|
+
/**
|
|
1305
|
+
* CTA Button Usage (non-blocking)
|
|
1306
|
+
*
|
|
1307
|
+
* Detects cases where a CTA is visually styled like a button but implemented
|
|
1308
|
+
* as <Link> / <a> with button-like classes. Prefer using our `Button` component
|
|
1309
|
+
* (it supports `href` or `asChild` patterns) for consistent padding, focus,
|
|
1310
|
+
* hover, and accessibility.
|
|
1311
|
+
*/
|
|
1312
|
+
async checkCTAButtons() {
|
|
1313
|
+
const startTime = Date.now();
|
|
1314
|
+
const issues = [];
|
|
1315
|
+
const files = await file_cache_1.fileCache.getAppAndComponentsTSX();
|
|
1316
|
+
const looksLikeButtonClasses = (text) => {
|
|
1317
|
+
// Intentionally conservative: background + padding + rounded is the typical "button" signature.
|
|
1318
|
+
const hasBg = /\bbg-\[|\bbg-[a-z0-9-]+\b/.test(text);
|
|
1319
|
+
const hasPadding = /\b(?:px|py|p)-(?:\d+|\[[^\]]+\])\b/.test(text);
|
|
1320
|
+
const hasRounded = /\brounded\b|rounded-\[/.test(text);
|
|
1321
|
+
const hasInteractive = /\bhover:|\bfocus-visible:|\bactive:|\btransition\b/.test(text);
|
|
1322
|
+
return hasBg && hasPadding && hasRounded && hasInteractive;
|
|
1323
|
+
};
|
|
1324
|
+
const looksLikeCTAContent = (text) => {
|
|
1325
|
+
// Common CTA verbs; keep small to avoid noise.
|
|
1326
|
+
return /(\bSell\b|\bBuy\b|\bCheckout\b|\bAdd to cart\b|\bList\b|\bCreate\b|\bContinue\b|\bSave\b|\bSubmit\b)/i.test(text);
|
|
1327
|
+
};
|
|
1328
|
+
for (const file of files) {
|
|
1329
|
+
const content = fs.readFileSync(file, "utf8");
|
|
1330
|
+
const lines = content.split("\n");
|
|
1331
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1332
|
+
const line = lines[i];
|
|
1333
|
+
if (line.trim().startsWith("//"))
|
|
1334
|
+
continue;
|
|
1335
|
+
// Match opening tags for Link or anchor.
|
|
1336
|
+
const isLinkTag = /<\s*Link\b/.test(line);
|
|
1337
|
+
const isAnchorTag = /<\s*a\b/.test(line);
|
|
1338
|
+
if (!isLinkTag && !isAnchorTag)
|
|
1339
|
+
continue;
|
|
1340
|
+
const block = lines.slice(i, Math.min(i + 8, lines.length)).join("\n");
|
|
1341
|
+
// Skip obvious non-CTA cases.
|
|
1342
|
+
if (/aria-label=\{?['"][^'"]*(?:Close|Open|Menu|Back|Next|Previous)[^'"]*['"]/i.test(block))
|
|
1343
|
+
continue;
|
|
1344
|
+
if (/role=\{?['"]menuitem['"]/i.test(block))
|
|
1345
|
+
continue;
|
|
1346
|
+
if (/\bicon\b/i.test(block) && /<\s*IconButton\b/.test(block))
|
|
1347
|
+
continue;
|
|
1348
|
+
// Heuristic: styled like a button and contains CTA-like copy nearby.
|
|
1349
|
+
const hasButtonLikeClasses = looksLikeButtonClasses(block);
|
|
1350
|
+
const nearbyText = lines.slice(i, Math.min(i + 15, lines.length)).join(" ");
|
|
1351
|
+
const hasCTAText = looksLikeCTAContent(nearbyText);
|
|
1352
|
+
const explicitlyButtonRole = /role=\{?['"]button['"]/i.test(block);
|
|
1353
|
+
if ((hasButtonLikeClasses && hasCTAText) || explicitlyButtonRole) {
|
|
1354
|
+
issues.push({
|
|
1355
|
+
file,
|
|
1356
|
+
line: i + 1,
|
|
1357
|
+
type: "cta-link-should-be-button",
|
|
1358
|
+
severity: "warning",
|
|
1359
|
+
message: "CTA appears styled like a button but implemented as Link/a",
|
|
1360
|
+
suggestion: 'Use <Button href="..."> or <Button asChild><Link ... /></Button> for consistent styling/accessibility',
|
|
1361
|
+
snippet: line.trim().substring(0, 140),
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
return {
|
|
1367
|
+
name: `CTA Button Usage (${issues.length} warnings)`,
|
|
1368
|
+
passed: true,
|
|
1369
|
+
blocking: true,
|
|
1370
|
+
issues,
|
|
1371
|
+
duration: Date.now() - startTime,
|
|
1372
|
+
};
|
|
1373
|
+
}
|
|
1374
|
+
async runAll() {
|
|
1375
|
+
const startTime = Date.now();
|
|
1376
|
+
console.log(`\n${console_chars_1.emoji.palette} CONSOLIDATED UI PATTERNS PREFLIGHT`);
|
|
1377
|
+
console.log((0, console_chars_1.createDivider)(80, "heavy"));
|
|
1378
|
+
const checks = [];
|
|
1379
|
+
checks.push(await this.checkCategoryChips());
|
|
1380
|
+
checks.push(await this.checkChipSizeConsistency());
|
|
1381
|
+
checks.push(await this.checkGlassmorphism());
|
|
1382
|
+
checks.push(await this.checkFlexJustify());
|
|
1383
|
+
checks.push(await this.checkLucideIcons());
|
|
1384
|
+
checks.push(await this.checkToastPolish());
|
|
1385
|
+
checks.push(await this.checkCardContentPadding());
|
|
1386
|
+
checks.push(await this.checkProductPagePolish());
|
|
1387
|
+
checks.push(await this.checkGlobalPolish());
|
|
1388
|
+
checks.push(await this.checkAutocompleteFloatingLabels());
|
|
1389
|
+
checks.push(await this.checkCTAButtons());
|
|
1390
|
+
checks.push(await this.checkCssCircular());
|
|
1391
|
+
checks.push(await this.checkZIndex());
|
|
1392
|
+
checks.push(await this.checkUndefinedCssVariables());
|
|
1393
|
+
checks.push(await this.checkHeaderIconButtonUniformity());
|
|
1394
|
+
const totalDuration = Date.now() - startTime;
|
|
1395
|
+
const allIssues = checks.flatMap((c) => c.issues);
|
|
1396
|
+
const hasBlockingFailure = checks.some((c) => !c.passed && c.blocking);
|
|
1397
|
+
const summary = {
|
|
1398
|
+
total: checks.length,
|
|
1399
|
+
passed: checks.filter((c) => c.passed).length,
|
|
1400
|
+
failed: checks.filter((c) => !c.passed).length,
|
|
1401
|
+
errors: allIssues.filter((i) => i.severity === "error").length,
|
|
1402
|
+
warnings: allIssues.filter((i) => i.severity === "warning").length,
|
|
1403
|
+
};
|
|
1404
|
+
this.printResults(checks, totalDuration, summary, hasBlockingFailure);
|
|
1405
|
+
return { module: "ui-patterns", passed: !hasBlockingFailure, totalDuration, checks, summary };
|
|
1406
|
+
}
|
|
1407
|
+
printResults(checks, totalDuration, summary, hasBlockingFailure) {
|
|
1408
|
+
console.log("\n" + (0, console_chars_1.createDivider)(80, "heavy"));
|
|
1409
|
+
console.log(`${console_chars_1.emoji.chart} UI PATTERNS RESULTS`);
|
|
1410
|
+
console.log((0, console_chars_1.createDivider)(80, "heavy"));
|
|
1411
|
+
checks.forEach((check) => {
|
|
1412
|
+
const icon = check.passed
|
|
1413
|
+
? `${console_chars_1.emoji.success}`
|
|
1414
|
+
: check.blocking
|
|
1415
|
+
? `${console_chars_1.emoji.error}`
|
|
1416
|
+
: `${console_chars_1.emoji.warning}`;
|
|
1417
|
+
const count = check.issues.length > 0 ? ` (${check.issues.length} issues)` : "";
|
|
1418
|
+
console.log(`${icon} ${check.name.padEnd(30)} ${(check.duration / 1000).toFixed(1)}s${count}`);
|
|
1419
|
+
if (this.verbose && check.issues.length > 0) {
|
|
1420
|
+
check.issues.slice(0, 3).forEach((issue) => {
|
|
1421
|
+
console.log(` ${issue.file}:${issue.line} - ${issue.message}`);
|
|
1422
|
+
});
|
|
1423
|
+
if (check.issues.length > 3)
|
|
1424
|
+
console.log(` ... and ${check.issues.length - 3} more`);
|
|
1425
|
+
}
|
|
1426
|
+
});
|
|
1427
|
+
console.log((0, console_chars_1.createDivider)(80, "heavy"));
|
|
1428
|
+
console.log(`Errors: ${summary.errors} | Warnings: ${summary.warnings} | Time: ${(totalDuration / 1000).toFixed(1)}s`);
|
|
1429
|
+
if (hasBlockingFailure) {
|
|
1430
|
+
console.log(`\n${console_chars_1.emoji.error} UI PATTERNS FAILED (blocking errors found)`);
|
|
1431
|
+
}
|
|
1432
|
+
else {
|
|
1433
|
+
console.log(`\n${console_chars_1.emoji.success} UI PATTERNS PASSED`);
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
exports.UIPatternsPreflightModule = UIPatternsPreflightModule;
|
|
1438
|
+
async function main() {
|
|
1439
|
+
const reporter = (0, universal_progress_reporter_1.createUniversalProgressReporter)(path.basename(__filename, ".ts"));
|
|
1440
|
+
const args = process.argv.slice(2);
|
|
1441
|
+
const flags = new Set(args.filter((a) => a.startsWith("-")));
|
|
1442
|
+
const positional = args.filter((a) => !a.startsWith("-"));
|
|
1443
|
+
const mode = positional[0] || "all";
|
|
1444
|
+
const verbose = flags.has("--verbose") || flags.has("-v");
|
|
1445
|
+
const strictUniformity = flags.has("--strict") ||
|
|
1446
|
+
flags.has("--strict-uniformity") ||
|
|
1447
|
+
process.env.PREFLIGHT_STRICT_UNIFORMITY === "1";
|
|
1448
|
+
const module = new UIPatternsPreflightModule({ verbose, strictUniformity });
|
|
1449
|
+
const runSingle = async (name, fn) => {
|
|
1450
|
+
const check = await fn();
|
|
1451
|
+
const hasBlockingFailure = !check.passed && check.blocking;
|
|
1452
|
+
console.log(`\n${check.passed ? "${emoji.success}" : "${emoji.error}"} ${check.name}: ${check.issues.length} issues`);
|
|
1453
|
+
if (check.issues.length > 0) {
|
|
1454
|
+
const severityRank = { error: 0, warning: 1, info: 2 };
|
|
1455
|
+
const issuesSorted = [...check.issues].sort((a, b) => {
|
|
1456
|
+
const ar = severityRank[a.severity] ?? 9;
|
|
1457
|
+
const br = severityRank[b.severity] ?? 9;
|
|
1458
|
+
if (ar !== br)
|
|
1459
|
+
return ar - br;
|
|
1460
|
+
if (a.file !== b.file)
|
|
1461
|
+
return a.file.localeCompare(b.file);
|
|
1462
|
+
return (a.line ?? 0) - (b.line ?? 0);
|
|
1463
|
+
});
|
|
1464
|
+
const toPrint = verbose ? issuesSorted : issuesSorted.slice(0, 5);
|
|
1465
|
+
toPrint.forEach((i) => {
|
|
1466
|
+
console.log(` [${i.severity}] ${i.file}:${i.line} - ${i.message}`);
|
|
1467
|
+
});
|
|
1468
|
+
if (!verbose && issuesSorted.length > 5)
|
|
1469
|
+
console.log(` ... and ${issuesSorted.length - 5} more`);
|
|
1470
|
+
}
|
|
1471
|
+
return {
|
|
1472
|
+
module: `ui-patterns:${name}`,
|
|
1473
|
+
passed: !hasBlockingFailure,
|
|
1474
|
+
totalDuration: check.duration,
|
|
1475
|
+
checks: [check],
|
|
1476
|
+
summary: {
|
|
1477
|
+
total: 1,
|
|
1478
|
+
passed: check.passed ? 1 : 0,
|
|
1479
|
+
failed: check.passed ? 0 : 1,
|
|
1480
|
+
errors: check.issues.filter((i) => i.severity === "error").length,
|
|
1481
|
+
warnings: check.issues.filter((i) => i.severity === "warning").length,
|
|
1482
|
+
},
|
|
1483
|
+
};
|
|
1484
|
+
};
|
|
1485
|
+
let result;
|
|
1486
|
+
switch (mode) {
|
|
1487
|
+
case "category":
|
|
1488
|
+
result = await runSingle("category", () => module.checkCategoryChips());
|
|
1489
|
+
break;
|
|
1490
|
+
case "chip-size":
|
|
1491
|
+
result = await runSingle("chip-size", () => module.checkChipSizeConsistency());
|
|
1492
|
+
break;
|
|
1493
|
+
case "glass":
|
|
1494
|
+
result = await runSingle("glass", () => module.checkGlassmorphism());
|
|
1495
|
+
break;
|
|
1496
|
+
case "flex":
|
|
1497
|
+
result = await runSingle("flex", () => module.checkFlexJustify());
|
|
1498
|
+
break;
|
|
1499
|
+
case "icons":
|
|
1500
|
+
result = await runSingle("icons", () => module.checkLucideIcons());
|
|
1501
|
+
break;
|
|
1502
|
+
case "polish":
|
|
1503
|
+
result = await runSingle("polish", () => module.checkGlobalPolish());
|
|
1504
|
+
break;
|
|
1505
|
+
case "product-polish":
|
|
1506
|
+
result = await runSingle("product-polish", () => module.checkProductPagePolish());
|
|
1507
|
+
break;
|
|
1508
|
+
case "cta":
|
|
1509
|
+
result = await runSingle("cta", () => module.checkCTAButtons());
|
|
1510
|
+
break;
|
|
1511
|
+
case "css":
|
|
1512
|
+
result = await runSingle("css", () => module.checkCssCircular());
|
|
1513
|
+
break;
|
|
1514
|
+
case "zindex":
|
|
1515
|
+
result = await runSingle("zindex", () => module.checkZIndex());
|
|
1516
|
+
break;
|
|
1517
|
+
case "undefined":
|
|
1518
|
+
result = await runSingle("undefined", () => module.checkUndefinedCssVariables());
|
|
1519
|
+
break;
|
|
1520
|
+
case "header-icons":
|
|
1521
|
+
result = await runSingle("header-icons", () => module.checkHeaderIconButtonUniformity());
|
|
1522
|
+
break;
|
|
1523
|
+
default:
|
|
1524
|
+
result = await module.runAll();
|
|
1525
|
+
break;
|
|
1526
|
+
}
|
|
1527
|
+
process.exit(result.passed ? 0 : 1);
|
|
1528
|
+
}
|
|
1529
|
+
if (require.main === module) {
|
|
1530
|
+
main();
|
|
1531
|
+
}
|
|
1532
|
+
//# sourceMappingURL=ui-patterns.js.map
|