@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,1371 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Consolidated UI Layout Preflight
|
|
5
|
+
*
|
|
6
|
+
* Combines layout checks into one comprehensive module:
|
|
7
|
+
* - page-template-enforcement (layout templates) - BLOCKING
|
|
8
|
+
* - container-spacing (pt/pb balance) - BLOCKING
|
|
9
|
+
* - container-centering (Container in flex layouts needs wrapper) - BLOCKING
|
|
10
|
+
* - page-content-centering (frontend pages need maxWidth + margin auto) - BLOCKING
|
|
11
|
+
* - page-width-consistency (only 80rem or full width allowed) - WARNING
|
|
12
|
+
* - header-content-spacing (content after UnifiedHeader needs mt) - WARNING
|
|
13
|
+
* - breadcrumb-gap (breadcrumbs in gapped flex containers) - WARNING
|
|
14
|
+
* - content-padding (sidebar content area padding consistency) - WARNING
|
|
15
|
+
* - section-spacing (gaps between sections)
|
|
16
|
+
* - excessive-spacing (py-12+ detection) - BLOCKING
|
|
17
|
+
* - sidebar-maxwidth (no hardcoded maxWidth in sidebar layouts) - BLOCKING
|
|
18
|
+
* - filter-card-layout (horizontal filter cards) - BLOCKING
|
|
19
|
+
* - filter-section-in-card (filter sections must use Card, not Paper) - BLOCKING
|
|
20
|
+
* - page-content-wrapper-consistency (Box vs Tailwind)
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* pnpm preflight:ui-layout # All layout checks
|
|
24
|
+
* pnpm preflight:ui-layout templates # Page templates only
|
|
25
|
+
* pnpm preflight:ui-layout containers # Container spacing only
|
|
26
|
+
* pnpm preflight:ui-layout centering # Container centering only
|
|
27
|
+
* pnpm preflight:ui-layout page-centering # Page content centering only
|
|
28
|
+
* pnpm preflight:ui-layout page-width # Page width consistency only
|
|
29
|
+
* pnpm preflight:ui-layout header-content # Header-content spacing only
|
|
30
|
+
* pnpm preflight:ui-layout breadcrumb-gap # Breadcrumb gap check only
|
|
31
|
+
* pnpm preflight:ui-layout content-padding # Content area padding consistency only
|
|
32
|
+
* pnpm preflight:ui-layout sections # Section spacing only
|
|
33
|
+
* pnpm preflight:ui-layout excessive # Excessive spacing only
|
|
34
|
+
* pnpm preflight:ui-layout sidebar # Sidebar maxWidth only
|
|
35
|
+
* pnpm preflight:ui-layout filters # Filter card layout only
|
|
36
|
+
* pnpm preflight:ui-layout filter-card # Filter section in card only
|
|
37
|
+
* pnpm preflight:ui-layout wrappers # Content wrappers only
|
|
38
|
+
*/
|
|
39
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
40
|
+
if (k2 === undefined) k2 = k;
|
|
41
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
42
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
43
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
44
|
+
}
|
|
45
|
+
Object.defineProperty(o, k2, desc);
|
|
46
|
+
}) : (function(o, m, k, k2) {
|
|
47
|
+
if (k2 === undefined) k2 = k;
|
|
48
|
+
o[k2] = m[k];
|
|
49
|
+
}));
|
|
50
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
51
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
52
|
+
}) : function(o, v) {
|
|
53
|
+
o["default"] = v;
|
|
54
|
+
});
|
|
55
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
56
|
+
var ownKeys = function(o) {
|
|
57
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
58
|
+
var ar = [];
|
|
59
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
60
|
+
return ar;
|
|
61
|
+
};
|
|
62
|
+
return ownKeys(o);
|
|
63
|
+
};
|
|
64
|
+
return function (mod) {
|
|
65
|
+
if (mod && mod.__esModule) return mod;
|
|
66
|
+
var result = {};
|
|
67
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
68
|
+
__setModuleDefault(result, mod);
|
|
69
|
+
return result;
|
|
70
|
+
};
|
|
71
|
+
})();
|
|
72
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
73
|
+
exports.UILayoutPreflightModule = void 0;
|
|
74
|
+
const fs = __importStar(require("fs"));
|
|
75
|
+
const path = __importStar(require("path"));
|
|
76
|
+
const console_chars_1 = require("../../utils/console-chars");
|
|
77
|
+
const file_cache_1 = require("../../shared/file-cache");
|
|
78
|
+
const universal_progress_reporter_1 = require("../system/universal-progress-reporter");
|
|
79
|
+
const concurrency_config_1 = require("../../shared/concurrency-config");
|
|
80
|
+
// Cached file getters
|
|
81
|
+
let _cachedPageFiles = null;
|
|
82
|
+
async function getCachedPageFiles() {
|
|
83
|
+
if (!_cachedPageFiles) {
|
|
84
|
+
_cachedPageFiles = await file_cache_1.fileCache.getPageFiles();
|
|
85
|
+
}
|
|
86
|
+
return _cachedPageFiles;
|
|
87
|
+
}
|
|
88
|
+
let _cachedClientFiles = null;
|
|
89
|
+
async function getCachedClientFiles() {
|
|
90
|
+
if (!_cachedClientFiles) {
|
|
91
|
+
_cachedClientFiles = await file_cache_1.fileCache.getClientFiles();
|
|
92
|
+
}
|
|
93
|
+
return _cachedClientFiles;
|
|
94
|
+
}
|
|
95
|
+
let _cachedAppTsxFiles = null;
|
|
96
|
+
async function getCachedAppTsxFiles() {
|
|
97
|
+
if (!_cachedAppTsxFiles) {
|
|
98
|
+
_cachedAppTsxFiles = await file_cache_1.fileCache.getAppTSX();
|
|
99
|
+
}
|
|
100
|
+
return _cachedAppTsxFiles;
|
|
101
|
+
}
|
|
102
|
+
let _cachedAppComponentsTsxFiles = null;
|
|
103
|
+
async function getCachedAppComponentsTsxFiles() {
|
|
104
|
+
if (!_cachedAppComponentsTsxFiles) {
|
|
105
|
+
_cachedAppComponentsTsxFiles = await file_cache_1.fileCache.getAppAndComponentsTSX();
|
|
106
|
+
}
|
|
107
|
+
return _cachedAppComponentsTsxFiles;
|
|
108
|
+
}
|
|
109
|
+
const ALLOWED_TEMPLATES = [
|
|
110
|
+
"PageLayout",
|
|
111
|
+
"PageContainer",
|
|
112
|
+
"SectionLayout",
|
|
113
|
+
"ContentPageLayout",
|
|
114
|
+
"ContentLayout",
|
|
115
|
+
"DashboardLayout",
|
|
116
|
+
"LayoutContainer",
|
|
117
|
+
"ServerLayout",
|
|
118
|
+
"SellerPageLayout",
|
|
119
|
+
"AdminPageLayout",
|
|
120
|
+
"AccountPageLayout",
|
|
121
|
+
"BuyerPageLayout",
|
|
122
|
+
"AuthLayout",
|
|
123
|
+
"AuthPageLayout",
|
|
124
|
+
"StandardPageLayout",
|
|
125
|
+
"TemplatesLayout",
|
|
126
|
+
"AnalyticsLayout",
|
|
127
|
+
"ListingsLayout",
|
|
128
|
+
];
|
|
129
|
+
const EXEMPT_PAGES = [
|
|
130
|
+
"app/layout.tsx",
|
|
131
|
+
"app/error.tsx",
|
|
132
|
+
"app/global-error.tsx",
|
|
133
|
+
"app/not-found.tsx",
|
|
134
|
+
"app/providers.tsx",
|
|
135
|
+
"app/HomePageClient.tsx",
|
|
136
|
+
"app/page.tsx",
|
|
137
|
+
// Dev-only tools and dashboards are not required to follow production layout templates
|
|
138
|
+
"app/dev/",
|
|
139
|
+
// Frontend pages with custom layouts (like homepage pattern)
|
|
140
|
+
"app/how-it-works/page.tsx",
|
|
141
|
+
"app/how-it-works/HowItWorksClient.tsx",
|
|
142
|
+
// Public store pages with custom layouts (stores use ServerLayout in parent)
|
|
143
|
+
"app/stores/[username]/policies/page.tsx",
|
|
144
|
+
"app/stores/[username]/policies/StorePoliciesClient.tsx",
|
|
145
|
+
// Pages that delegate to client components with layouts (detection sometimes fails on Windows paths)
|
|
146
|
+
"app/account/analytics/page.tsx",
|
|
147
|
+
"app/account/dashboard/page.tsx",
|
|
148
|
+
"app/store/orders/page.tsx",
|
|
149
|
+
// Redirect stubs
|
|
150
|
+
"app/account/listings/new/page.tsx",
|
|
151
|
+
// Client-only helpers colocated with pages (not actual page templates)
|
|
152
|
+
"app/product/[slug]/ProductPageClient.tsx",
|
|
153
|
+
// Client components that are not pages (filter wrappers, etc.)
|
|
154
|
+
"app/checklists/ChecklistsPageClient.tsx",
|
|
155
|
+
// Docs pages inherit layout from app/docs/layout.tsx (which uses ServerLayout)
|
|
156
|
+
"app/docs/page.tsx",
|
|
157
|
+
"app/docs/selling/page.tsx",
|
|
158
|
+
"app/docs/shipping/page.tsx",
|
|
159
|
+
"app/docs/grading/page.tsx",
|
|
160
|
+
"app/docs/getting-started/page.tsx",
|
|
161
|
+
"app/docs/faq/page.tsx",
|
|
162
|
+
"app/docs/integrations/page.tsx",
|
|
163
|
+
"app/docs/buying/page.tsx",
|
|
164
|
+
"app/docs/ai-recognition/page.tsx",
|
|
165
|
+
"app/docs/grid/page.tsx",
|
|
166
|
+
"app/docs/grid/GridDocumentationClient.tsx",
|
|
167
|
+
// Help pages use HelpPageLayout which wraps ServerLayout
|
|
168
|
+
"app/help/page.tsx",
|
|
169
|
+
"app/help/HelpClient.tsx",
|
|
170
|
+
"app/help/article/[articleId]/page.tsx",
|
|
171
|
+
"app/help/article/[articleId]/ArticleDetailClient.tsx",
|
|
172
|
+
];
|
|
173
|
+
// Get concurrency from shared config (respects PREFLIGHT_CONCURRENCY env var)
|
|
174
|
+
const concurrencyConfig = (0, concurrency_config_1.getConcurrencyConfig)();
|
|
175
|
+
class UILayoutPreflightModule {
|
|
176
|
+
verbose;
|
|
177
|
+
parallel = false;
|
|
178
|
+
clientComponentsWithLayout = new Set();
|
|
179
|
+
constructor(options = {}) {
|
|
180
|
+
this.verbose = options.verbose || false;
|
|
181
|
+
this.parallel = options.parallel || concurrencyConfig.parallel;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Check if a client component file uses a layout template (with recursion for delegation)
|
|
185
|
+
*/
|
|
186
|
+
checkClientComponentHasLayout(clientFilePath, visited = new Set()) {
|
|
187
|
+
// Normalize path for consistent comparison
|
|
188
|
+
const normalizedPath = clientFilePath.replace(/\\/g, "/");
|
|
189
|
+
// Prevent infinite recursion
|
|
190
|
+
if (visited.has(normalizedPath))
|
|
191
|
+
return false;
|
|
192
|
+
visited.add(normalizedPath);
|
|
193
|
+
try {
|
|
194
|
+
// Try both forward and backslash versions for Windows compatibility
|
|
195
|
+
let content;
|
|
196
|
+
try {
|
|
197
|
+
content = fs.readFileSync(normalizedPath, "utf8");
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
// Try with backslashes on Windows
|
|
201
|
+
content = fs.readFileSync(clientFilePath, "utf8");
|
|
202
|
+
}
|
|
203
|
+
// Direct layout usage
|
|
204
|
+
const hasTemplateImport = ALLOWED_TEMPLATES.some((t) => new RegExp(`import[\\s\\S]*?\\b${t}\\b[\\s\\S]*?from`, "i").test(content));
|
|
205
|
+
const usesTemplate = ALLOWED_TEMPLATES.some((t) => new RegExp(`<${t}[\\s>]`, "i").test(content));
|
|
206
|
+
if (hasTemplateImport && usesTemplate)
|
|
207
|
+
return true;
|
|
208
|
+
// Check if it's a re-export (e.g., export { X as Y } from "../../../../../...")
|
|
209
|
+
const reExportMatch = content.match(/export\s*\{[^}]*\}\s*from\s*["']([^"']+)["']/);
|
|
210
|
+
if (reExportMatch) {
|
|
211
|
+
const reExportPath = reExportMatch[1];
|
|
212
|
+
if (reExportPath.startsWith("@/")) {
|
|
213
|
+
// Alias import - assume it has layout if it's a known component path
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// Check if it delegates to another client component (renders <SomeClient />)
|
|
218
|
+
const delegateMatch = content.match(/<(\w+Client)[\s\/>]/);
|
|
219
|
+
if (delegateMatch) {
|
|
220
|
+
const delegatedComponent = delegateMatch[1];
|
|
221
|
+
const importMatch = content.match(new RegExp(`import\\s*\\{[^}]*${delegatedComponent}[^}]*\\}\\s*from\\s*["']([^"']+)["']`));
|
|
222
|
+
if (importMatch) {
|
|
223
|
+
const importPath = importMatch[1];
|
|
224
|
+
if (importPath.startsWith("@/")) {
|
|
225
|
+
// Alias import to known component - assume it has layout
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Check if a page.tsx delegates to a client component that has a layout
|
|
238
|
+
*/
|
|
239
|
+
pageRendersClientWithLayout(content, pageDir) {
|
|
240
|
+
// Pattern: <SomeClient /> anywhere in the return statement (including inside fragments)
|
|
241
|
+
// This handles: return <SomeClient />, return (<><script/><SomeClient /></>), etc.
|
|
242
|
+
const clientComponentMatch = content.match(/<(\w+Client)[\s\/>]/);
|
|
243
|
+
if (!clientComponentMatch)
|
|
244
|
+
return false;
|
|
245
|
+
const clientComponentName = clientComponentMatch[1];
|
|
246
|
+
// Check for import of this client component (handles both default and named imports)
|
|
247
|
+
// Default: import SomeClient from "./SomeClient"
|
|
248
|
+
// Named: import { SomeClient } from "./SomeClient"
|
|
249
|
+
// Named with others: import { SomeClient, other } from "./SomeClient"
|
|
250
|
+
const defaultImportMatch = content.match(new RegExp(`import\\s+${clientComponentName}\\s+from\\s*["']([^"']+)["']`));
|
|
251
|
+
const namedImportMatch = content.match(new RegExp(`import\\s*\\{[^}]*\\b${clientComponentName}\\b[^}]*\\}\\s*from\\s*["']([^"']+)["']`));
|
|
252
|
+
const importMatch = defaultImportMatch || namedImportMatch;
|
|
253
|
+
if (!importMatch)
|
|
254
|
+
return false;
|
|
255
|
+
const importPath = importMatch[1];
|
|
256
|
+
// Resolve the client component file path
|
|
257
|
+
let clientFilePath;
|
|
258
|
+
if (importPath.startsWith("./") || importPath.startsWith("../")) {
|
|
259
|
+
// Relative import - resolve from page directory
|
|
260
|
+
// Normalize pageDir to use forward slashes for consistency
|
|
261
|
+
const normalizedPageDir = pageDir.replace(/\\/g, "/");
|
|
262
|
+
clientFilePath = path.join(normalizedPageDir, importPath).replace(/\\/g, "/");
|
|
263
|
+
if (!clientFilePath.endsWith(".tsx"))
|
|
264
|
+
clientFilePath += ".tsx";
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
// Could be an alias like @/ - skip for now, assume it has layout
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
// Check if the client component uses a layout template
|
|
271
|
+
return this.checkClientComponentHasLayout(clientFilePath);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Check if a client component file is valid (has layout, re-exports, or delegates)
|
|
275
|
+
*/
|
|
276
|
+
isClientComponentValid(content, file) {
|
|
277
|
+
// Direct layout usage - check for import (handles multi-line imports)
|
|
278
|
+
const hasTemplateImport = ALLOWED_TEMPLATES.some((t) => new RegExp(`import[\\s\\S]*?\\b${t}\\b[\\s\\S]*?from`, "i").test(content));
|
|
279
|
+
const usesTemplate = ALLOWED_TEMPLATES.some((t) => new RegExp(`<${t}[\\s>]`, "i").test(content));
|
|
280
|
+
if (hasTemplateImport && usesTemplate)
|
|
281
|
+
return true;
|
|
282
|
+
// Re-export pattern (e.g., export { X as Y } from "../../../../../...")
|
|
283
|
+
const reExportMatch = content.match(/export\s*\{[^}]*\}\s*from\s*["']([^"']+)["']/);
|
|
284
|
+
if (reExportMatch)
|
|
285
|
+
return true;
|
|
286
|
+
// Delegates to another client component that uses @/ alias (assumed to have layout)
|
|
287
|
+
const delegateMatch = content.match(/<(\w+Client)[\s\/>]/);
|
|
288
|
+
if (delegateMatch) {
|
|
289
|
+
const delegatedComponent = delegateMatch[1];
|
|
290
|
+
const importMatch = content.match(new RegExp(`import\\s*\\{[^}]*${delegatedComponent}[^}]*\\}\\s*from\\s*["']@/`));
|
|
291
|
+
if (importMatch)
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Page Template Enforcement - BLOCKING
|
|
298
|
+
*/
|
|
299
|
+
async checkPageTemplates() {
|
|
300
|
+
const startTime = Date.now();
|
|
301
|
+
const issues = [];
|
|
302
|
+
const pageFiles = await getCachedPageFiles();
|
|
303
|
+
const clientFiles = await getCachedClientFiles();
|
|
304
|
+
const allFiles = [...pageFiles, ...clientFiles];
|
|
305
|
+
for (const file of allFiles) {
|
|
306
|
+
const normalizedFile = file.replace(/\\/g, "/");
|
|
307
|
+
if (EXEMPT_PAGES.some((exempt) => normalizedFile.includes(exempt)))
|
|
308
|
+
continue;
|
|
309
|
+
const content = fs.readFileSync(file, "utf8");
|
|
310
|
+
const isPageFile = file.endsWith("page.tsx");
|
|
311
|
+
const isClientFile = file.endsWith("Client.tsx");
|
|
312
|
+
const pageDir = path.dirname(file);
|
|
313
|
+
const hasTemplateImport = ALLOWED_TEMPLATES.some((t) => new RegExp(`import[\\s\\S]*?\\b${t}\\b[\\s\\S]*?from`, "i").test(content));
|
|
314
|
+
const usesTemplate = ALLOWED_TEMPLATES.some((t) => new RegExp(`<${t}[\\s>]`, "i").test(content));
|
|
315
|
+
if (!hasTemplateImport || !usesTemplate) {
|
|
316
|
+
const isRedirectOnly = content.includes("redirect(") && !content.includes("return (");
|
|
317
|
+
const isReExport = /export\s*\{[^}]*default[^}]*\}\s*from/.test(content);
|
|
318
|
+
// Check if this is a page.tsx that delegates to a client component with layout
|
|
319
|
+
const delegatesToClientWithLayout = isPageFile && this.pageRendersClientWithLayout(content, pageDir);
|
|
320
|
+
// Check if this is a client component that re-exports or delegates to another valid component
|
|
321
|
+
const isValidClientComponent = isClientFile && this.isClientComponentValid(content, file);
|
|
322
|
+
if (!isRedirectOnly &&
|
|
323
|
+
!isReExport &&
|
|
324
|
+
!delegatesToClientWithLayout &&
|
|
325
|
+
!isValidClientComponent) {
|
|
326
|
+
issues.push({
|
|
327
|
+
file,
|
|
328
|
+
line: 1,
|
|
329
|
+
type: "missing-template",
|
|
330
|
+
severity: "error",
|
|
331
|
+
message: "Page missing layout template",
|
|
332
|
+
suggestion: "Wrap content in <PageLayout> or <SectionLayout>",
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return {
|
|
338
|
+
name: "Page Template Enforcement",
|
|
339
|
+
passed: issues.length === 0,
|
|
340
|
+
blocking: true,
|
|
341
|
+
issues,
|
|
342
|
+
duration: Date.now() - startTime,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Container Spacing (pt/pb balance) - BLOCKING
|
|
347
|
+
*/
|
|
348
|
+
async checkContainerSpacing() {
|
|
349
|
+
const startTime = Date.now();
|
|
350
|
+
const issues = [];
|
|
351
|
+
const files = await getCachedAppTsxFiles();
|
|
352
|
+
const containerPattern = /<Container[^>]*sx=\{\{[^}]*flex:\s*1[^}]*pb:[^}]*\}\}/g;
|
|
353
|
+
for (const file of files) {
|
|
354
|
+
const content = fs.readFileSync(file, "utf8");
|
|
355
|
+
const lines = content.split("\n");
|
|
356
|
+
let match;
|
|
357
|
+
containerPattern.lastIndex = 0;
|
|
358
|
+
while ((match = containerPattern.exec(content)) !== null) {
|
|
359
|
+
if (!match[0].includes("pt:")) {
|
|
360
|
+
const lineNumber = content.substring(0, match.index).split("\n").length;
|
|
361
|
+
issues.push({
|
|
362
|
+
file,
|
|
363
|
+
line: lineNumber,
|
|
364
|
+
type: "container-missing-pt",
|
|
365
|
+
severity: "error",
|
|
366
|
+
message: "Container has pb but missing pt (causes huge gap after header)",
|
|
367
|
+
suggestion: 'Add pt to match pb: sx={{ flex: 1, pt: "var(--spacing-8)", pb: "var(--spacing-8)" }}',
|
|
368
|
+
snippet: lines[lineNumber - 1]?.trim().substring(0, 80),
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return {
|
|
374
|
+
name: "Container Spacing",
|
|
375
|
+
passed: issues.length === 0,
|
|
376
|
+
blocking: true,
|
|
377
|
+
issues,
|
|
378
|
+
duration: Date.now() - startTime,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Header-Content Structure - Checks for proper content structure after UnifiedHeader variant="page"
|
|
383
|
+
*
|
|
384
|
+
* Standard:
|
|
385
|
+
* - Content after UnifiedHeader variant="page" SHOULD be wrapped in <Stack spacing={3}> (rule 10b intent)
|
|
386
|
+
* - Do NOT add mt-* / marginTop immediately after the header; UnifiedHeader already provides marginBottom.
|
|
387
|
+
*/
|
|
388
|
+
async checkHeaderContentSpacing() {
|
|
389
|
+
const startTime = Date.now();
|
|
390
|
+
const issues = [];
|
|
391
|
+
// Check client components that use UnifiedHeader with variant="page"
|
|
392
|
+
const files = await getCachedClientFiles();
|
|
393
|
+
for (const file of files) {
|
|
394
|
+
const content = fs.readFileSync(file, "utf8");
|
|
395
|
+
const lines = content.split("\n");
|
|
396
|
+
// Find UnifiedHeader with variant="page"
|
|
397
|
+
const headerPattern = /<UnifiedHeader[^>]*variant=["']page["'][^>]*\/>/g;
|
|
398
|
+
let match;
|
|
399
|
+
while ((match = headerPattern.exec(content)) !== null) {
|
|
400
|
+
const headerEndIndex = match.index + match[0].length;
|
|
401
|
+
const lineNumber = content.substring(0, headerEndIndex).split("\n").length;
|
|
402
|
+
// Get the next 800 chars after the header to find the first content element
|
|
403
|
+
const afterHeader = content.substring(headerEndIndex, headerEndIndex + 800);
|
|
404
|
+
// Get the full opening tag of the first element
|
|
405
|
+
const fullTagMatch = afterHeader.match(/^\s*<(\w+)[^>]*>/s);
|
|
406
|
+
if (!fullTagMatch)
|
|
407
|
+
continue;
|
|
408
|
+
const fullTag = fullTagMatch[0];
|
|
409
|
+
const elementName = fullTagMatch[1];
|
|
410
|
+
// Skip if it's a fragment, comment, or another UnifiedHeader
|
|
411
|
+
if (elementName === ">" || elementName === "UnifiedHeader")
|
|
412
|
+
continue;
|
|
413
|
+
// Get the actual line where the first element starts
|
|
414
|
+
const elementLineNumber = lineNumber + afterHeader.substring(0, fullTagMatch.index).split("\n").length - 1;
|
|
415
|
+
// Check if wrapped in Stack (best practice per rule 10b)
|
|
416
|
+
const isStack = elementName === "Stack";
|
|
417
|
+
// VIOLATION: Not using Stack wrapper
|
|
418
|
+
if (!isStack) {
|
|
419
|
+
issues.push({
|
|
420
|
+
file,
|
|
421
|
+
line: elementLineNumber,
|
|
422
|
+
type: "header-content-not-stack",
|
|
423
|
+
severity: "warning",
|
|
424
|
+
message: `Content after UnifiedHeader variant="page" should use a Stack wrapper (spacing={3})`,
|
|
425
|
+
suggestion: `Wrap content in <Stack spacing={3}> (do not add mt-*)`,
|
|
426
|
+
snippet: lines[elementLineNumber - 1]?.trim().substring(0, 100),
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
// Stack is used - warn if it adds marginTop right after a page header.
|
|
431
|
+
const hasMtClass = /className=["'][^"']*\bmt-\d+\b/.test(fullTag);
|
|
432
|
+
const hasMtStyle = /mt:\s*["']var\(--spacing-\d+\)["']/.test(fullTag) ||
|
|
433
|
+
/marginTop:\s*["']var\(--spacing-\d+\)["']/.test(fullTag);
|
|
434
|
+
if (hasMtClass || hasMtStyle) {
|
|
435
|
+
issues.push({
|
|
436
|
+
file,
|
|
437
|
+
line: elementLineNumber,
|
|
438
|
+
type: "header-content-has-mt",
|
|
439
|
+
severity: "warning",
|
|
440
|
+
message: `Stack after UnifiedHeader has marginTop; this usually creates doubled spacing`,
|
|
441
|
+
suggestion: `Remove mt/marginTop from the Stack after UnifiedHeader (header already has marginBottom)`,
|
|
442
|
+
snippet: lines[elementLineNumber - 1]?.trim().substring(0, 100),
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return {
|
|
449
|
+
name: "Header-Content Structure",
|
|
450
|
+
passed: issues.filter((i) => i.severity === "error").length === 0,
|
|
451
|
+
blocking: false, // Warning-only guidance
|
|
452
|
+
issues,
|
|
453
|
+
duration: Date.now() - startTime,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Section Spacing (gaps between sections)
|
|
458
|
+
*/
|
|
459
|
+
async checkSectionSpacing() {
|
|
460
|
+
const startTime = Date.now();
|
|
461
|
+
const issues = [];
|
|
462
|
+
const files = await file_cache_1.fileCache.getFiles("{app,components}/**/*.{tsx,jsx}", {
|
|
463
|
+
ignore: ["**/node_modules/**", "**/.next/**", "**/ui/**"],
|
|
464
|
+
});
|
|
465
|
+
for (const file of files) {
|
|
466
|
+
const content = fs.readFileSync(file, "utf8");
|
|
467
|
+
const lines = content.split("\n");
|
|
468
|
+
lines.forEach((line, index) => {
|
|
469
|
+
// Check for consecutive sections without gap
|
|
470
|
+
if (line.includes("</section>") || line.includes("</SectionLayout>")) {
|
|
471
|
+
const nextLine = lines[index + 1];
|
|
472
|
+
if (nextLine && (nextLine.includes("<section") || nextLine.includes("<SectionLayout"))) {
|
|
473
|
+
const prevLines = lines.slice(Math.max(0, index - 10), index).join("\n");
|
|
474
|
+
if (!prevLines.includes("gap:") &&
|
|
475
|
+
!prevLines.includes('gap="') &&
|
|
476
|
+
!prevLines.includes("gap-")) {
|
|
477
|
+
issues.push({
|
|
478
|
+
file,
|
|
479
|
+
line: index + 2,
|
|
480
|
+
type: "missing-section-gap",
|
|
481
|
+
severity: "warning",
|
|
482
|
+
message: "Consecutive sections without gap",
|
|
483
|
+
suggestion: 'Add gap: "var(--spacing-12)" to parent container',
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
return {
|
|
491
|
+
name: "Section Spacing",
|
|
492
|
+
passed: true,
|
|
493
|
+
blocking: true,
|
|
494
|
+
issues,
|
|
495
|
+
duration: Date.now() - startTime,
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Excessive Spacing Detection (py-12+) - BLOCKING
|
|
500
|
+
*/
|
|
501
|
+
async checkExcessiveSpacing() {
|
|
502
|
+
const startTime = Date.now();
|
|
503
|
+
const issues = [];
|
|
504
|
+
const files = await getCachedAppComponentsTsxFiles();
|
|
505
|
+
const excessivePatterns = [
|
|
506
|
+
{ regex: /className="[^"]*\b(py-1[2-9]|py-2[0-9])\b/g, type: "py" },
|
|
507
|
+
{ regex: /className="[^"]*\b(mb-1[2-9]|mb-2[0-9])\b/g, type: "mb" },
|
|
508
|
+
{ regex: /className="[^"]*\b(mt-1[2-9]|mt-2[0-9])\b/g, type: "mt" },
|
|
509
|
+
{ regex: /className="[^"]*\b(gap-1[2-9]|gap-2[0-9])\b/g, type: "gap" },
|
|
510
|
+
];
|
|
511
|
+
for (const file of files) {
|
|
512
|
+
const content = fs.readFileSync(file, "utf8");
|
|
513
|
+
const lines = content.split("\n");
|
|
514
|
+
lines.forEach((line, index) => {
|
|
515
|
+
excessivePatterns.forEach(({ regex, type }) => {
|
|
516
|
+
regex.lastIndex = 0;
|
|
517
|
+
const matches = [...line.matchAll(regex)];
|
|
518
|
+
matches.forEach((match) => {
|
|
519
|
+
issues.push({
|
|
520
|
+
file,
|
|
521
|
+
line: index + 1,
|
|
522
|
+
type: `excessive-${type}`,
|
|
523
|
+
severity: "error",
|
|
524
|
+
message: `Excessive spacing "${match[1]}" (48px+) causes huge gaps`,
|
|
525
|
+
suggestion: "Use var(--spacing-8) or smaller",
|
|
526
|
+
snippet: line.trim().substring(0, 80),
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
});
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
return {
|
|
533
|
+
name: "Excessive Spacing",
|
|
534
|
+
passed: issues.length === 0,
|
|
535
|
+
blocking: true,
|
|
536
|
+
issues,
|
|
537
|
+
duration: Date.now() - startTime,
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Sidebar MaxWidth Constraints - BLOCKING
|
|
542
|
+
* Detects hardcoded maxWidth in sidebar layouts which causes inconsistent widths
|
|
543
|
+
*/
|
|
544
|
+
async checkSidebarMaxWidth() {
|
|
545
|
+
const startTime = Date.now();
|
|
546
|
+
const issues = [];
|
|
547
|
+
const files = await getCachedAppTsxFiles();
|
|
548
|
+
for (const file of files) {
|
|
549
|
+
const content = fs.readFileSync(file, "utf8");
|
|
550
|
+
const lines = content.split("\n");
|
|
551
|
+
// Check if file has a sidebar layout
|
|
552
|
+
const hasSidebar = /SellerSidebar|AdminSidebar|BuyerSidebar/.test(content);
|
|
553
|
+
if (!hasSidebar)
|
|
554
|
+
continue;
|
|
555
|
+
// Check for nested Box with hardcoded maxWidth in style prop
|
|
556
|
+
const styleMaxWidthPattern = /<Box[^>]*style=\{[^}]*maxWidth:\s*["']?\d+(?:px)?["']?/g;
|
|
557
|
+
let match;
|
|
558
|
+
while ((match = styleMaxWidthPattern.exec(content)) !== null) {
|
|
559
|
+
const lineNumber = content.substring(0, match.index).split("\n").length;
|
|
560
|
+
issues.push({
|
|
561
|
+
file,
|
|
562
|
+
line: lineNumber,
|
|
563
|
+
type: "sidebar-maxwidth",
|
|
564
|
+
severity: "error",
|
|
565
|
+
message: "Hardcoded maxWidth in sidebar layout causes inconsistent widths",
|
|
566
|
+
suggestion: 'Remove maxWidth. Use: <Box sx={{ flex: 1, px: "var(--spacing-4)", pb: "var(--spacing-8)" }}>',
|
|
567
|
+
snippet: lines[lineNumber - 1]?.trim().substring(0, 80),
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
// Check for nested Box with hardcoded maxWidth in sx prop
|
|
571
|
+
const sxMaxWidthPattern = /<Box[^>]*sx=\{[^}]*maxWidth:\s*(?:\d+|["']\d+)/g;
|
|
572
|
+
while ((match = sxMaxWidthPattern.exec(content)) !== null) {
|
|
573
|
+
const lineNumber = content.substring(0, match.index).split("\n").length;
|
|
574
|
+
issues.push({
|
|
575
|
+
file,
|
|
576
|
+
line: lineNumber,
|
|
577
|
+
type: "sidebar-maxwidth",
|
|
578
|
+
severity: "error",
|
|
579
|
+
message: "Hardcoded maxWidth in sidebar layout causes inconsistent widths",
|
|
580
|
+
suggestion: 'Remove maxWidth. Use: <Box sx={{ flex: 1, px: "var(--spacing-4)", pb: "var(--spacing-8)" }}>',
|
|
581
|
+
snippet: lines[lineNumber - 1]?.trim().substring(0, 80),
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return {
|
|
586
|
+
name: "Sidebar MaxWidth Constraints",
|
|
587
|
+
passed: issues.length === 0,
|
|
588
|
+
blocking: true,
|
|
589
|
+
issues,
|
|
590
|
+
duration: Date.now() - startTime,
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Filter Card Layout - BLOCKING
|
|
595
|
+
* Detects filter cards using Stack with responsive direction that doesn't work
|
|
596
|
+
* Filter cards should use inline styles with flexDirection: "row" and flexWrap: "wrap"
|
|
597
|
+
*
|
|
598
|
+
* Only checks files that are explicitly filter components (by filename)
|
|
599
|
+
*/
|
|
600
|
+
async checkFilterCardLayout() {
|
|
601
|
+
const startTime = Date.now();
|
|
602
|
+
const issues = [];
|
|
603
|
+
// Only check files that are explicitly filter components by filename
|
|
604
|
+
const allFiles = await getCachedAppComponentsTsxFiles();
|
|
605
|
+
const filterFiles = allFiles.filter((f) => /(?:Filter|Filters)[^/]*\.tsx$/.test(f));
|
|
606
|
+
for (const file of filterFiles) {
|
|
607
|
+
const content = fs.readFileSync(file, "utf8");
|
|
608
|
+
const lines = content.split("\n");
|
|
609
|
+
// Check for Stack with responsive direction object (doesn't work reliably)
|
|
610
|
+
const brokenPattern = /<Stack[^>]*direction=\{\{\s*xs:\s*["']column["'][^}]*(?:sm|md|lg):\s*["']row["']/g;
|
|
611
|
+
let match;
|
|
612
|
+
while ((match = brokenPattern.exec(content)) !== null) {
|
|
613
|
+
const lineNumber = content.substring(0, match.index).split("\n").length;
|
|
614
|
+
issues.push({
|
|
615
|
+
file,
|
|
616
|
+
line: lineNumber,
|
|
617
|
+
type: "filter-broken-responsive",
|
|
618
|
+
severity: "error",
|
|
619
|
+
message: "Filter card uses Stack with responsive direction object (unreliable with @supercatch/ui)",
|
|
620
|
+
suggestion: 'Use div with style={{ display: "flex", flexDirection: "row", flexWrap: "wrap", gap: "var(--spacing-3)" }}',
|
|
621
|
+
snippet: lines[lineNumber - 1]?.trim().substring(0, 80),
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return {
|
|
626
|
+
name: "Filter Card Layout",
|
|
627
|
+
passed: issues.length === 0,
|
|
628
|
+
blocking: true,
|
|
629
|
+
issues,
|
|
630
|
+
duration: Date.now() - startTime,
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Filter Section in Card - BLOCKING
|
|
635
|
+
* Detects filter sections using Paper instead of Card component.
|
|
636
|
+
* Filter sections (containing Select dropdowns for filtering) should use Card with CardContent.
|
|
637
|
+
*
|
|
638
|
+
* Pattern to detect: <Paper> containing <Select> elements used for filtering
|
|
639
|
+
* Correct pattern: <Card><CardContent><Select>...</Select></CardContent></Card>
|
|
640
|
+
*/
|
|
641
|
+
async checkFilterSectionInCard() {
|
|
642
|
+
const startTime = Date.now();
|
|
643
|
+
const issues = [];
|
|
644
|
+
// Check client components that might have filter sections
|
|
645
|
+
const files = await getCachedClientFiles();
|
|
646
|
+
for (const file of files) {
|
|
647
|
+
const content = fs.readFileSync(file, "utf8");
|
|
648
|
+
const lines = content.split("\n");
|
|
649
|
+
// Pattern: Paper containing filter-like content (Selects with filter-related values)
|
|
650
|
+
// Look for Paper elements that have Select children with "all" or filter-like MenuItems
|
|
651
|
+
const paperPattern = /<Paper[^>]*>/g;
|
|
652
|
+
let match;
|
|
653
|
+
while ((match = paperPattern.exec(content)) !== null) {
|
|
654
|
+
const startIndex = match.index;
|
|
655
|
+
const lineNumber = content.substring(0, startIndex).split("\n").length;
|
|
656
|
+
// Find the closing Paper tag to get the content between
|
|
657
|
+
let depth = 1;
|
|
658
|
+
let endIndex = startIndex + match[0].length;
|
|
659
|
+
while (depth > 0 && endIndex < content.length) {
|
|
660
|
+
const nextOpen = content.indexOf("<Paper", endIndex);
|
|
661
|
+
const nextClose = content.indexOf("</Paper>", endIndex);
|
|
662
|
+
if (nextClose === -1)
|
|
663
|
+
break;
|
|
664
|
+
if (nextOpen !== -1 && nextOpen < nextClose) {
|
|
665
|
+
depth++;
|
|
666
|
+
endIndex = nextOpen + 6;
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
669
|
+
depth--;
|
|
670
|
+
endIndex = nextClose + 8;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
const paperContent = content.substring(startIndex, endIndex);
|
|
674
|
+
// Check if this Paper contains filter-like Select elements
|
|
675
|
+
const hasFilterSelect =
|
|
676
|
+
// Contains Select elements
|
|
677
|
+
/<Select[^>]*>/.test(paperContent) &&
|
|
678
|
+
// AND has filter-related menu items (All Platforms, All Status, etc.)
|
|
679
|
+
(/MenuItem[^>]*value=["']all["']/.test(paperContent) ||
|
|
680
|
+
/MenuItem[^>]*>All\s+(Platforms?|Status|Orders?|Types?|Categories?)/.test(paperContent) ||
|
|
681
|
+
// Or filter-related comments
|
|
682
|
+
/\{\/\*\s*Filter/.test(paperContent));
|
|
683
|
+
if (hasFilterSelect) {
|
|
684
|
+
issues.push({
|
|
685
|
+
file,
|
|
686
|
+
line: lineNumber,
|
|
687
|
+
type: "filter-not-in-card",
|
|
688
|
+
severity: "error",
|
|
689
|
+
message: "Filter section uses Paper instead of Card component",
|
|
690
|
+
suggestion: 'Use <Card sx={{ mb: "var(--spacing-4)" }}><CardContent sx={{ p: "var(--spacing-3)" }}>...</CardContent></Card>',
|
|
691
|
+
snippet: lines[lineNumber - 1]?.trim().substring(0, 80),
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
return {
|
|
697
|
+
name: "Filter Section in Card",
|
|
698
|
+
passed: issues.length === 0,
|
|
699
|
+
blocking: true,
|
|
700
|
+
issues,
|
|
701
|
+
duration: Date.now() - startTime,
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Page Content Wrapper Consistency (Box vs Tailwind)
|
|
706
|
+
*
|
|
707
|
+
* Detects content wrappers using Tailwind padding classes (px-4, pb-8) instead of
|
|
708
|
+
* design tokens via style prop. This is especially important for pages with sidebars
|
|
709
|
+
* where consistent spacing is critical.
|
|
710
|
+
*
|
|
711
|
+
* ${emoji.error} WRONG: <Box className="flex-1 px-4 pb-8">
|
|
712
|
+
* ${emoji.success} CORRECT: <Box style={{ flex: 1, paddingLeft: "var(--spacing-4)", paddingRight: "var(--spacing-4)", paddingBottom: "var(--spacing-8)" }}>
|
|
713
|
+
*/
|
|
714
|
+
async checkContentWrappers() {
|
|
715
|
+
const startTime = Date.now();
|
|
716
|
+
const issues = [];
|
|
717
|
+
const files = await getCachedPageFiles();
|
|
718
|
+
const clientFiles = await getCachedClientFiles();
|
|
719
|
+
for (const file of [...files, ...clientFiles]) {
|
|
720
|
+
const content = fs.readFileSync(file, "utf8");
|
|
721
|
+
const lines = content.split("\n");
|
|
722
|
+
// Check both <div> and <Box> elements with Tailwind padding classes
|
|
723
|
+
const tailwindPaddingPatterns = [
|
|
724
|
+
/<div\s+className="[^"]*\b(px-\d+|py-\d+|pb-\d+|pt-\d+)\b[^"]*">/g,
|
|
725
|
+
/<Box\s+className="[^"]*\b(px-\d+|py-\d+|pb-\d+|pt-\d+)\b[^"]*">/g,
|
|
726
|
+
];
|
|
727
|
+
// Check if file uses proper Box with style prop for padding
|
|
728
|
+
const hasProperStylePadding = /<Box[^>]*style=\{[^}]*padding(?:Left|Right|Top|Bottom)?:\s*["']var\(--spacing-\d+\)["'][^}]*\}/.test(content) || /<Box[^>]*sx=\{[^}]*px:\s*["']var\(--spacing-\d+\)["'][^}]*\}/.test(content);
|
|
729
|
+
for (const pattern of tailwindPaddingPatterns) {
|
|
730
|
+
let match;
|
|
731
|
+
pattern.lastIndex = 0;
|
|
732
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
733
|
+
const lineNumber = content.substring(0, match.index).split("\n").length;
|
|
734
|
+
const contextBefore = content.substring(Math.max(0, match.index - 500), match.index);
|
|
735
|
+
// Check if this is a main content wrapper (after breadcrumbs, contains page header, or is in sidebar layout)
|
|
736
|
+
const isMainWrapper = contextBefore.includes("<Breadcrumbs") ||
|
|
737
|
+
contextBefore.includes('variant="page"') ||
|
|
738
|
+
contextBefore.includes("Sidebar") ||
|
|
739
|
+
contextBefore.includes("MobileFilterWrapper");
|
|
740
|
+
// Skip loading spinners and simple utility containers
|
|
741
|
+
const matchedLine = lines[lineNumber - 1] || "";
|
|
742
|
+
const isLoadingSpinner = matchedLine.includes("justify-center") &&
|
|
743
|
+
(matchedLine.includes("py-8") || matchedLine.includes("py-4")) &&
|
|
744
|
+
!matchedLine.includes("px-");
|
|
745
|
+
const isSimpleUtility = !matchedLine.includes("flex-1") &&
|
|
746
|
+
!matchedLine.includes("px-") &&
|
|
747
|
+
matchedLine.includes("py-") &&
|
|
748
|
+
matchedLine.split(/\s+/).length <= 4;
|
|
749
|
+
// Skip card header patterns (min-h-11 flex items-center is standard card header)
|
|
750
|
+
const isCardHeader = matchedLine.includes("min-h-11") &&
|
|
751
|
+
matchedLine.includes("flex") &&
|
|
752
|
+
matchedLine.includes("items-center");
|
|
753
|
+
// Skip if preflight-ignore comment is on previous line
|
|
754
|
+
const prevLine = lines[lineNumber - 2] || "";
|
|
755
|
+
const hasPrevLineIgnore = prevLine.includes("preflight-ignore");
|
|
756
|
+
if (isMainWrapper &&
|
|
757
|
+
!hasProperStylePadding &&
|
|
758
|
+
!isLoadingSpinner &&
|
|
759
|
+
!isSimpleUtility &&
|
|
760
|
+
!isCardHeader &&
|
|
761
|
+
!hasPrevLineIgnore) {
|
|
762
|
+
const elementType = match[0].startsWith("<Box") ? "Box" : "div";
|
|
763
|
+
issues.push({
|
|
764
|
+
file,
|
|
765
|
+
line: lineNumber,
|
|
766
|
+
type: "tailwind-padding-on-wrapper",
|
|
767
|
+
severity: "warning",
|
|
768
|
+
message: `Content wrapper <${elementType}> uses Tailwind padding classes instead of design tokens`,
|
|
769
|
+
suggestion: 'Replace className with style={{ paddingLeft: "var(--spacing-4)", paddingRight: "var(--spacing-4)", paddingBottom: "var(--spacing-8)" }}',
|
|
770
|
+
snippet: lines[lineNumber - 1]?.trim().substring(0, 80),
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
return {
|
|
777
|
+
name: "Content Wrapper Consistency",
|
|
778
|
+
passed: issues.length === 0,
|
|
779
|
+
blocking: false, // Non-blocking - style preference, not functional issue
|
|
780
|
+
issues,
|
|
781
|
+
duration: Date.now() - startTime,
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Container Centering in Flex Layouts - BLOCKING
|
|
786
|
+
*
|
|
787
|
+
* Detects Container components inside ServerLayout (flex column) that aren't
|
|
788
|
+
* properly centered. In flex containers, children with width: 100% don't respond
|
|
789
|
+
* to margin: auto - they need a wrapper with justify-center.
|
|
790
|
+
*
|
|
791
|
+
* ${emoji.error} WRONG:
|
|
792
|
+
* <ServerLayout>
|
|
793
|
+
* <Container maxWidth="lg">...</Container> // Not centered!
|
|
794
|
+
* </ServerLayout>
|
|
795
|
+
*
|
|
796
|
+
* ${emoji.success} CORRECT:
|
|
797
|
+
* <ServerLayout>
|
|
798
|
+
* <Box className="flex-1 flex justify-center">
|
|
799
|
+
* <Container maxWidth="lg">...</Container>
|
|
800
|
+
* </Box>
|
|
801
|
+
* </ServerLayout>
|
|
802
|
+
*/
|
|
803
|
+
async checkContainerCentering() {
|
|
804
|
+
const startTime = Date.now();
|
|
805
|
+
const issues = [];
|
|
806
|
+
const files = await getCachedPageFiles();
|
|
807
|
+
for (const file of files) {
|
|
808
|
+
const content = fs.readFileSync(file, "utf8");
|
|
809
|
+
const lines = content.split("\n");
|
|
810
|
+
// Check if file uses ServerLayout
|
|
811
|
+
if (!/<ServerLayout/.test(content))
|
|
812
|
+
continue;
|
|
813
|
+
// Find Container elements that are direct children of ServerLayout (not wrapped in centering Box)
|
|
814
|
+
// Pattern: ServerLayout > ... > Container without a flex justify-center wrapper
|
|
815
|
+
const containerPattern = /<Container[^>]*maxWidth=/g;
|
|
816
|
+
let match;
|
|
817
|
+
while ((match = containerPattern.exec(content)) !== null) {
|
|
818
|
+
const containerIndex = match.index;
|
|
819
|
+
const lineNumber = content.substring(0, containerIndex).split("\n").length;
|
|
820
|
+
// Look backwards to find the parent context (up to 500 chars)
|
|
821
|
+
const contextBefore = content.substring(Math.max(0, containerIndex - 500), containerIndex);
|
|
822
|
+
// Check if Container is wrapped in a centering flex container
|
|
823
|
+
const hasCenteringWrapper = /flex[^"]*justify-center/.test(contextBefore) ||
|
|
824
|
+
/display:\s*["']?flex["']?[^}]*justifyContent:\s*["']?center/.test(contextBefore) ||
|
|
825
|
+
/justify-content:\s*center/.test(contextBefore);
|
|
826
|
+
// Check if this Container is inside a sidebar layout (those have different centering needs)
|
|
827
|
+
const isInSidebarLayout = /SellerPageLayout|AdminPageLayout|AccountPageLayout|BuyerPageLayout/.test(content) ||
|
|
828
|
+
/Sidebar/.test(content) ||
|
|
829
|
+
// Flex row layouts (sidebar patterns)
|
|
830
|
+
/flex-row|flexDirection:\s*["']row/.test(content);
|
|
831
|
+
// Check if Container is a direct child after header/breadcrumbs (main content area)
|
|
832
|
+
const isMainContent = contextBefore.includes("<Breadcrumbs") ||
|
|
833
|
+
contextBefore.includes("<UnifiedHeader") ||
|
|
834
|
+
contextBefore.includes("</UnifiedHeader>");
|
|
835
|
+
if (!hasCenteringWrapper && !isInSidebarLayout && isMainContent) {
|
|
836
|
+
issues.push({
|
|
837
|
+
file,
|
|
838
|
+
line: lineNumber,
|
|
839
|
+
type: "container-not-centered",
|
|
840
|
+
severity: "error",
|
|
841
|
+
message: "Container in ServerLayout not centered (flex children need wrapper)",
|
|
842
|
+
suggestion: 'Wrap Container in <Box className="flex-1 flex justify-center">',
|
|
843
|
+
snippet: lines[lineNumber - 1]?.trim().substring(0, 80),
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
return {
|
|
849
|
+
name: "Container Centering",
|
|
850
|
+
passed: issues.length === 0,
|
|
851
|
+
blocking: true,
|
|
852
|
+
issues,
|
|
853
|
+
duration: Date.now() - startTime,
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Page Content Centering - BLOCKING
|
|
858
|
+
*
|
|
859
|
+
* Detects frontend pages (Client components with UnifiedHeader variant="navigation")
|
|
860
|
+
* that are missing proper page-level centering. These pages should use the standard
|
|
861
|
+
* pattern: maxWidth: "80rem" + marginLeft: "auto" + marginRight: "auto"
|
|
862
|
+
*
|
|
863
|
+
* This catches issues like the how-it-works page where content was left-justified
|
|
864
|
+
* because it used a flex column layout without proper centering on the main content.
|
|
865
|
+
*
|
|
866
|
+
* ${emoji.error} WRONG:
|
|
867
|
+
* <main style={{ flex: 1, paddingLeft: "var(--spacing-4)" }}>
|
|
868
|
+
* <h1>Page Title</h1> // Left-justified!
|
|
869
|
+
* </main>
|
|
870
|
+
*
|
|
871
|
+
* ${emoji.success} CORRECT:
|
|
872
|
+
* <main style={{
|
|
873
|
+
* flex: 1,
|
|
874
|
+
* maxWidth: "80rem",
|
|
875
|
+
* marginLeft: "auto",
|
|
876
|
+
* marginRight: "auto",
|
|
877
|
+
* paddingLeft: "var(--spacing-4)",
|
|
878
|
+
* paddingRight: "var(--spacing-4)"
|
|
879
|
+
* }}>
|
|
880
|
+
* <h1>Page Title</h1> // Centered!
|
|
881
|
+
* </main>
|
|
882
|
+
*/
|
|
883
|
+
async checkPageContentCentering() {
|
|
884
|
+
const startTime = Date.now();
|
|
885
|
+
const issues = [];
|
|
886
|
+
// Check client components that use UnifiedHeader variant="navigation" (frontend pages)
|
|
887
|
+
const clientFiles = await getCachedClientFiles();
|
|
888
|
+
// Pages that are exempt from this check (use different layout patterns)
|
|
889
|
+
const exemptPatterns = [
|
|
890
|
+
"HomePageClient", // Homepage has special hero layout
|
|
891
|
+
"ChecklistsPageClient", // Filter wrapper
|
|
892
|
+
];
|
|
893
|
+
for (const file of clientFiles) {
|
|
894
|
+
const normalizedFile = file.replace(/\\/g, "/");
|
|
895
|
+
// Skip exempt files
|
|
896
|
+
if (exemptPatterns.some((pattern) => normalizedFile.includes(pattern)))
|
|
897
|
+
continue;
|
|
898
|
+
const content = fs.readFileSync(file, "utf8");
|
|
899
|
+
const lines = content.split("\n");
|
|
900
|
+
// Only check pages with UnifiedHeader variant="navigation" (frontend pages)
|
|
901
|
+
if (!/<UnifiedHeader[^>]*variant=["']navigation["']/.test(content))
|
|
902
|
+
continue;
|
|
903
|
+
// Skip pages that use layout components (they handle centering)
|
|
904
|
+
if (/SellerPageLayout|AdminPageLayout|AccountPageLayout|BuyerPageLayout|ServerLayout|PageLayout|ContentPageLayout/.test(content))
|
|
905
|
+
continue;
|
|
906
|
+
// Skip pages with sidebars (different centering pattern)
|
|
907
|
+
if (/Sidebar/.test(content))
|
|
908
|
+
continue;
|
|
909
|
+
// Find <main> elements and check for proper centering
|
|
910
|
+
const mainPattern = /<main[^>]*>/g;
|
|
911
|
+
let match;
|
|
912
|
+
while ((match = mainPattern.exec(content)) !== null) {
|
|
913
|
+
const mainIndex = match.index;
|
|
914
|
+
const lineNumber = content.substring(0, mainIndex).split("\n").length;
|
|
915
|
+
const mainTag = match[0];
|
|
916
|
+
// Get the full style prop (may span multiple lines)
|
|
917
|
+
const afterMain = content.substring(mainIndex, mainIndex + 1000);
|
|
918
|
+
const styleMatch = afterMain.match(/style=\{(\{[\s\S]*?\})\}/);
|
|
919
|
+
const styleContent = styleMatch ? styleMatch[1] : "";
|
|
920
|
+
// Check for proper centering pattern
|
|
921
|
+
const hasMaxWidth = /maxWidth:\s*["']80rem["']/.test(styleContent) ||
|
|
922
|
+
/maxWidth:\s*["']1280px["']/.test(styleContent);
|
|
923
|
+
const hasMarginAuto = /marginLeft:\s*["']auto["']/.test(styleContent) &&
|
|
924
|
+
/marginRight:\s*["']auto["']/.test(styleContent);
|
|
925
|
+
const hasMxAuto = /mx:\s*["']auto["']/.test(styleContent) ||
|
|
926
|
+
/margin:\s*["'][^"']*auto[^"']*["']/.test(styleContent);
|
|
927
|
+
// Also check className for mx-auto (less preferred but acceptable)
|
|
928
|
+
const hasClassMxAuto = /className=["'][^"']*\bmx-auto\b/.test(mainTag);
|
|
929
|
+
const isProperlycentered = hasMaxWidth && (hasMarginAuto || hasMxAuto || hasClassMxAuto);
|
|
930
|
+
if (!isProperlycentered) {
|
|
931
|
+
issues.push({
|
|
932
|
+
file,
|
|
933
|
+
line: lineNumber,
|
|
934
|
+
type: "page-content-not-centered",
|
|
935
|
+
severity: "error",
|
|
936
|
+
message: "Frontend page <main> missing proper centering (content will be left-justified)",
|
|
937
|
+
suggestion: 'Add to <main> style: maxWidth: "80rem", marginLeft: "auto", marginRight: "auto"',
|
|
938
|
+
snippet: lines[lineNumber - 1]?.trim().substring(0, 80),
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return {
|
|
944
|
+
name: "Page Content Centering",
|
|
945
|
+
passed: issues.length === 0,
|
|
946
|
+
blocking: true,
|
|
947
|
+
issues,
|
|
948
|
+
duration: Date.now() - startTime,
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
/**
|
|
952
|
+
* Page Container Width Consistency - WARNING
|
|
953
|
+
*
|
|
954
|
+
* Only two valid page width patterns exist:
|
|
955
|
+
* 1. Standard width: 80rem (1280px) - homepage, how-it-works, docs, etc.
|
|
956
|
+
* 2. Full width: No maxWidth - card collections, category browsing, etc.
|
|
957
|
+
*
|
|
958
|
+
* Any other maxWidth value (1200px, 1400px, 1920px) causes visual jarring
|
|
959
|
+
* when navigating between pages.
|
|
960
|
+
*
|
|
961
|
+
* ${emoji.success} CORRECT: maxWidth: "80rem" or maxWidth: "1280px"
|
|
962
|
+
* ${emoji.success} CORRECT: No maxWidth (full width for collections/browsing)
|
|
963
|
+
* ${emoji.warning} WARNING: maxWidth: "1200px", "1400px", "1920px", etc.
|
|
964
|
+
*
|
|
965
|
+
* Exceptions:
|
|
966
|
+
* - Content-specific containers (modals, cards, text blocks < 900px)
|
|
967
|
+
* - Tables with minWidth (horizontal scroll)
|
|
968
|
+
*/
|
|
969
|
+
async checkPageContainerWidthConsistency() {
|
|
970
|
+
const startTime = Date.now();
|
|
971
|
+
const issues = [];
|
|
972
|
+
const clientFiles = await getCachedClientFiles();
|
|
973
|
+
// Files/patterns to skip (content containers, not page containers)
|
|
974
|
+
const skipFilePatterns = [
|
|
975
|
+
"Modal",
|
|
976
|
+
"Dialog",
|
|
977
|
+
"Toast",
|
|
978
|
+
"Tooltip",
|
|
979
|
+
"Dropdown",
|
|
980
|
+
"Card",
|
|
981
|
+
"Alert",
|
|
982
|
+
"Badge",
|
|
983
|
+
"Chip",
|
|
984
|
+
"ErrorBoundary",
|
|
985
|
+
"Skeleton",
|
|
986
|
+
"Navigation",
|
|
987
|
+
];
|
|
988
|
+
for (const file of clientFiles) {
|
|
989
|
+
const normalizedFile = file.replace(/\\/g, "/");
|
|
990
|
+
// Skip non-page containers
|
|
991
|
+
if (skipFilePatterns.some((pattern) => normalizedFile.includes(pattern)))
|
|
992
|
+
continue;
|
|
993
|
+
const content = fs.readFileSync(file, "utf8");
|
|
994
|
+
const lines = content.split("\n");
|
|
995
|
+
// Look for maxWidth in style props
|
|
996
|
+
const maxWidthPattern = /maxWidth:\s*["'](\d+)(px|rem)?["']/g;
|
|
997
|
+
let match;
|
|
998
|
+
while ((match = maxWidthPattern.exec(content)) !== null) {
|
|
999
|
+
const value = parseInt(match[1], 10);
|
|
1000
|
+
const unit = match[2] || "px";
|
|
1001
|
+
const lineNumber = content.substring(0, match.index).split("\n").length;
|
|
1002
|
+
const line = lines[lineNumber - 1] || "";
|
|
1003
|
+
// Convert rem to px for comparison (1rem = 16px)
|
|
1004
|
+
const pxValue = unit === "rem" ? value * 16 : value;
|
|
1005
|
+
// Skip small values (content containers like text blocks, cards, paragraphs)
|
|
1006
|
+
// These are intentionally constrained for readability
|
|
1007
|
+
if (pxValue < 900)
|
|
1008
|
+
continue;
|
|
1009
|
+
// Skip minWidth (tables, horizontal scroll)
|
|
1010
|
+
if (line.includes("minWidth"))
|
|
1011
|
+
continue;
|
|
1012
|
+
// Skip if it's inside a content container context (not page-level)
|
|
1013
|
+
const contextBefore = content.substring(Math.max(0, match.index - 300), match.index);
|
|
1014
|
+
if (/CardContent|Modal|Dialog|Alert|Toast|Table|<p\s|<span\s/.test(contextBefore))
|
|
1015
|
+
continue;
|
|
1016
|
+
// Skip inner content grids (e.g., pricing cards grid with 1000px)
|
|
1017
|
+
// These are intentionally constrained for visual balance
|
|
1018
|
+
if (/gridTemplateColumns|display:\s*["']grid["']/.test(contextBefore))
|
|
1019
|
+
continue;
|
|
1020
|
+
// Check if this is the standard width (80rem = 1280px)
|
|
1021
|
+
const isStandardWidth = pxValue === 1280 || (unit === "rem" && value === 80);
|
|
1022
|
+
// Flag non-standard page widths >= 1000px
|
|
1023
|
+
if (!isStandardWidth && pxValue >= 1000) {
|
|
1024
|
+
issues.push({
|
|
1025
|
+
file,
|
|
1026
|
+
line: lineNumber,
|
|
1027
|
+
type: "inconsistent-page-width",
|
|
1028
|
+
severity: "warning",
|
|
1029
|
+
message: `Non-standard page width: ${match[1]}${unit}. Use either 80rem (standard) or no maxWidth (full width)`,
|
|
1030
|
+
suggestion: 'Standard pages: maxWidth: "80rem". Collection/browse pages: remove maxWidth for full width',
|
|
1031
|
+
snippet: line.trim().substring(0, 80),
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
return {
|
|
1037
|
+
name: "Page Container Width Consistency",
|
|
1038
|
+
passed: issues.length === 0,
|
|
1039
|
+
blocking: true, // Warning only
|
|
1040
|
+
issues,
|
|
1041
|
+
duration: Date.now() - startTime,
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
/**
|
|
1045
|
+
* Breadcrumb Gap Check - WARNING
|
|
1046
|
+
*
|
|
1047
|
+
* Detects when UnifiedBreadcrumbs is placed inside a flex container with large gap,
|
|
1048
|
+
* which causes unwanted spacing above the breadcrumbs.
|
|
1049
|
+
*
|
|
1050
|
+
* ${emoji.error} WRONG:
|
|
1051
|
+
* <main style={{ display: "flex", flexDirection: "column", gap: "var(--spacing-12)" }}>
|
|
1052
|
+
* <UnifiedBreadcrumbs /> // Large gap above breadcrumbs!
|
|
1053
|
+
* <div>Hero Section</div>
|
|
1054
|
+
* </main>
|
|
1055
|
+
*
|
|
1056
|
+
* ${emoji.success} CORRECT:
|
|
1057
|
+
* <main>
|
|
1058
|
+
* <UnifiedBreadcrumbs />
|
|
1059
|
+
* <div style={{ display: "flex", flexDirection: "column", gap: "var(--spacing-12)" }}>
|
|
1060
|
+
* <div>Hero Section</div>
|
|
1061
|
+
* <div>Other Content</div>
|
|
1062
|
+
* </div>
|
|
1063
|
+
* </main>
|
|
1064
|
+
*/
|
|
1065
|
+
async checkBreadcrumbGap() {
|
|
1066
|
+
const startTime = Date.now();
|
|
1067
|
+
const issues = [];
|
|
1068
|
+
const clientFiles = await getCachedClientFiles();
|
|
1069
|
+
// Files that have been manually verified or use different patterns
|
|
1070
|
+
const exemptPatterns = [
|
|
1071
|
+
"CategoryPageClient", // Uses noTopMargin correctly
|
|
1072
|
+
];
|
|
1073
|
+
for (const file of clientFiles) {
|
|
1074
|
+
const normalizedFile = file.replace(/\\/g, "/");
|
|
1075
|
+
// Skip exempt files
|
|
1076
|
+
if (exemptPatterns.some((pattern) => normalizedFile.includes(pattern)))
|
|
1077
|
+
continue;
|
|
1078
|
+
const content = fs.readFileSync(file, "utf8");
|
|
1079
|
+
// Skip files without breadcrumbs
|
|
1080
|
+
if (!content.includes("UnifiedBreadcrumbs"))
|
|
1081
|
+
continue;
|
|
1082
|
+
const lines = content.split("\n");
|
|
1083
|
+
// Look for pattern: flex column container with large gap containing breadcrumbs
|
|
1084
|
+
// This is a heuristic check - look for main/div with flex column + large gap
|
|
1085
|
+
const containerPattern = /<(main|div)[^>]*style=\{[^}]*flexDirection:\s*["']column["'][^}]*gap:\s*["']var\(--spacing-(8|10|12|16)\)["'][^}]*\}/g;
|
|
1086
|
+
let match;
|
|
1087
|
+
while ((match = containerPattern.exec(content)) !== null) {
|
|
1088
|
+
const containerStart = match.index;
|
|
1089
|
+
const lineNumber = content.substring(0, containerStart).split("\n").length;
|
|
1090
|
+
// Find the content between this container's opening and closing tags
|
|
1091
|
+
// Look for UnifiedBreadcrumbs within the next 2000 chars (reasonable container size)
|
|
1092
|
+
const afterContainer = content.substring(containerStart, containerStart + 2000);
|
|
1093
|
+
// Check if UnifiedBreadcrumbs appears as a direct child (within first few elements)
|
|
1094
|
+
// Look for breadcrumbs before any nested containers
|
|
1095
|
+
const breadcrumbMatch = afterContainer.match(/<UnifiedBreadcrumbs[^>]*\/?>/);
|
|
1096
|
+
if (breadcrumbMatch) {
|
|
1097
|
+
const breadcrumbIndex = breadcrumbMatch.index || 0;
|
|
1098
|
+
// Check if breadcrumbs is within the first 500 chars (likely direct child)
|
|
1099
|
+
// and not inside a nested div/section
|
|
1100
|
+
const beforeBreadcrumb = afterContainer.substring(0, breadcrumbIndex);
|
|
1101
|
+
const nestedContainerCount = (beforeBreadcrumb.match(/<(div|section|main)[^>]*>/g) || [])
|
|
1102
|
+
.length;
|
|
1103
|
+
// If breadcrumbs is a direct child (no nested containers before it)
|
|
1104
|
+
if (nestedContainerCount <= 1) {
|
|
1105
|
+
issues.push({
|
|
1106
|
+
file,
|
|
1107
|
+
line: lineNumber,
|
|
1108
|
+
type: "breadcrumb-in-gapped-container",
|
|
1109
|
+
severity: "warning",
|
|
1110
|
+
message: "UnifiedBreadcrumbs inside flex container with large gap causes unwanted spacing above breadcrumbs",
|
|
1111
|
+
suggestion: "Move breadcrumbs outside the gapped container, or wrap content sections in a separate div with the gap",
|
|
1112
|
+
snippet: lines[lineNumber - 1]?.trim().substring(0, 80),
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
return {
|
|
1119
|
+
name: "Breadcrumb Gap Check",
|
|
1120
|
+
passed: issues.length === 0,
|
|
1121
|
+
blocking: true, // Warning only
|
|
1122
|
+
issues,
|
|
1123
|
+
duration: Date.now() - startTime,
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Content Area Padding Consistency Check - WARNING
|
|
1128
|
+
*
|
|
1129
|
+
* Detects inconsistent horizontal padding in content areas next to sidebars.
|
|
1130
|
+
* All sidebar-adjacent content areas should use the same padding for visual consistency.
|
|
1131
|
+
*
|
|
1132
|
+
* Standard: var(--spacing-4) (16px) for content areas next to sidebars
|
|
1133
|
+
*
|
|
1134
|
+
* ${emoji.error} WRONG:
|
|
1135
|
+
* <Box style={{ paddingLeft: "var(--spacing-3)", paddingRight: "var(--spacing-3)" }}>
|
|
1136
|
+
* {content}
|
|
1137
|
+
* </Box>
|
|
1138
|
+
*
|
|
1139
|
+
* ${emoji.success} CORRECT:
|
|
1140
|
+
* <Box style={{ paddingLeft: "var(--spacing-4)", paddingRight: "var(--spacing-4)" }}>
|
|
1141
|
+
* {content}
|
|
1142
|
+
* </Box>
|
|
1143
|
+
*/
|
|
1144
|
+
async checkContentAreaPaddingConsistency() {
|
|
1145
|
+
const startTime = Date.now();
|
|
1146
|
+
const issues = [];
|
|
1147
|
+
// Files that define content area padding next to sidebars
|
|
1148
|
+
// NOTE: DashboardPageLayout is excluded - it has its own gutter rules (spacing-3)
|
|
1149
|
+
// checked by ui-spacing.ts Dashboard Gutter Consistency
|
|
1150
|
+
const layoutFiles = [
|
|
1151
|
+
"components/layout/AppShell.tsx",
|
|
1152
|
+
"app/**/CategoryPageClient.tsx",
|
|
1153
|
+
"app/cards/**/CategoryPageClient.tsx",
|
|
1154
|
+
"components/shared/CategoryPageLayout.tsx",
|
|
1155
|
+
].flatMap((pattern) => {
|
|
1156
|
+
// For specific files, check if they exist
|
|
1157
|
+
if (!pattern.includes("*")) {
|
|
1158
|
+
return fs.existsSync(pattern) ? [pattern] : [];
|
|
1159
|
+
}
|
|
1160
|
+
// For glob patterns, filter from cached files
|
|
1161
|
+
const regex = new RegExp(pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*"));
|
|
1162
|
+
return _cachedAppComponentsTsxFiles?.filter((f) => regex.test(f)) || [];
|
|
1163
|
+
});
|
|
1164
|
+
// Standard padding value
|
|
1165
|
+
const STANDARD_PADDING = "var(--spacing-4)";
|
|
1166
|
+
// Patterns to detect non-standard padding in content areas
|
|
1167
|
+
const paddingPatterns = [
|
|
1168
|
+
// paddingX prop with non-standard value
|
|
1169
|
+
/paddingX\s*[=:]\s*["']var\(--spacing-([^4]|[0-35-9]\d*)\)["']/g,
|
|
1170
|
+
// paddingLeft/Right with non-standard value (in style objects)
|
|
1171
|
+
/paddingLeft:\s*["']var\(--spacing-([^4]|[0-35-9]\d*)\)["']/g,
|
|
1172
|
+
/paddingRight:\s*["']var\(--spacing-([^4]|[0-35-9]\d*)\)["']/g,
|
|
1173
|
+
];
|
|
1174
|
+
for (const file of layoutFiles) {
|
|
1175
|
+
const normalizedFile = file.replace(/\\/g, "/");
|
|
1176
|
+
const content = fs.readFileSync(file, "utf8");
|
|
1177
|
+
const lines = content.split("\n");
|
|
1178
|
+
// Check if this file has sidebar-related content
|
|
1179
|
+
const hasSidebar = content.includes("Sidebar") ||
|
|
1180
|
+
content.includes("sidebar") ||
|
|
1181
|
+
content.includes("CategoryFilter");
|
|
1182
|
+
if (!hasSidebar)
|
|
1183
|
+
continue;
|
|
1184
|
+
for (const pattern of paddingPatterns) {
|
|
1185
|
+
let match;
|
|
1186
|
+
pattern.lastIndex = 0; // Reset regex state
|
|
1187
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
1188
|
+
const lineNumber = content.substring(0, match.index).split("\n").length;
|
|
1189
|
+
const line = lines[lineNumber - 1] || "";
|
|
1190
|
+
// Skip if it's a comment
|
|
1191
|
+
if (line.trim().startsWith("//") || line.trim().startsWith("*"))
|
|
1192
|
+
continue;
|
|
1193
|
+
// Skip if it's in a default prop definition that's being overridden
|
|
1194
|
+
if (line.includes("default") && line.includes("="))
|
|
1195
|
+
continue;
|
|
1196
|
+
issues.push({
|
|
1197
|
+
file: normalizedFile,
|
|
1198
|
+
line: lineNumber,
|
|
1199
|
+
type: "inconsistent-content-padding",
|
|
1200
|
+
severity: "warning",
|
|
1201
|
+
message: `Non-standard content area padding. Use ${STANDARD_PADDING} for consistency with other sidebar layouts.`,
|
|
1202
|
+
suggestion: `Change to ${STANDARD_PADDING} to match AppShell and other layout components`,
|
|
1203
|
+
snippet: line.trim().substring(0, 80),
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
return {
|
|
1209
|
+
name: "Content Area Padding Consistency",
|
|
1210
|
+
passed: issues.length === 0,
|
|
1211
|
+
blocking: false, // Warning only
|
|
1212
|
+
issues,
|
|
1213
|
+
duration: Date.now() - startTime,
|
|
1214
|
+
};
|
|
1215
|
+
}
|
|
1216
|
+
async runAll() {
|
|
1217
|
+
const startTime = Date.now();
|
|
1218
|
+
console.log("\n📐 CONSOLIDATED UI LAYOUT PREFLIGHT");
|
|
1219
|
+
console.log((0, console_chars_1.createDivider)(80, "heavy"));
|
|
1220
|
+
const checks = [];
|
|
1221
|
+
checks.push(await this.checkPageTemplates());
|
|
1222
|
+
checks.push(await this.checkContainerSpacing());
|
|
1223
|
+
checks.push(await this.checkContainerCentering());
|
|
1224
|
+
checks.push(await this.checkPageContentCentering());
|
|
1225
|
+
checks.push(await this.checkPageContainerWidthConsistency());
|
|
1226
|
+
checks.push(await this.checkHeaderContentSpacing());
|
|
1227
|
+
checks.push(await this.checkBreadcrumbGap());
|
|
1228
|
+
checks.push(await this.checkSectionSpacing());
|
|
1229
|
+
checks.push(await this.checkExcessiveSpacing());
|
|
1230
|
+
checks.push(await this.checkSidebarMaxWidth());
|
|
1231
|
+
checks.push(await this.checkFilterCardLayout());
|
|
1232
|
+
checks.push(await this.checkFilterSectionInCard());
|
|
1233
|
+
checks.push(await this.checkContentWrappers());
|
|
1234
|
+
checks.push(await this.checkContentAreaPaddingConsistency());
|
|
1235
|
+
const totalDuration = Date.now() - startTime;
|
|
1236
|
+
const allIssues = checks.flatMap((c) => c.issues);
|
|
1237
|
+
const errors = allIssues.filter((i) => i.severity === "error").length;
|
|
1238
|
+
const blockingFailed = checks.some((c) => c.blocking && !c.passed);
|
|
1239
|
+
const summary = {
|
|
1240
|
+
total: checks.length,
|
|
1241
|
+
passed: checks.filter((c) => c.passed).length,
|
|
1242
|
+
failed: checks.filter((c) => !c.passed).length,
|
|
1243
|
+
errors,
|
|
1244
|
+
warnings: allIssues.filter((i) => i.severity === "warning").length,
|
|
1245
|
+
};
|
|
1246
|
+
this.printResults(checks, totalDuration, summary);
|
|
1247
|
+
return {
|
|
1248
|
+
module: "ui-layout",
|
|
1249
|
+
passed: !blockingFailed,
|
|
1250
|
+
totalDuration,
|
|
1251
|
+
checks,
|
|
1252
|
+
summary,
|
|
1253
|
+
};
|
|
1254
|
+
}
|
|
1255
|
+
printResults(checks, totalDuration, summary) {
|
|
1256
|
+
console.log("\n" + (0, console_chars_1.createDivider)(80, "heavy"));
|
|
1257
|
+
console.log(`${console_chars_1.emoji.chart} UI LAYOUT RESULTS`);
|
|
1258
|
+
console.log((0, console_chars_1.createDivider)(80, "heavy"));
|
|
1259
|
+
checks.forEach((check) => {
|
|
1260
|
+
const icon = check.passed
|
|
1261
|
+
? `${console_chars_1.emoji.success}`
|
|
1262
|
+
: check.blocking
|
|
1263
|
+
? `${console_chars_1.emoji.error}`
|
|
1264
|
+
: `${console_chars_1.emoji.warning}`;
|
|
1265
|
+
const count = check.issues.length > 0 ? ` (${check.issues.length} issues)` : "";
|
|
1266
|
+
const blocking = check.blocking ? " [BLOCKING]" : "";
|
|
1267
|
+
console.log(`${icon} ${check.name.padEnd(30)} ${(check.duration / 1000).toFixed(1)}s${count}${blocking}`);
|
|
1268
|
+
});
|
|
1269
|
+
console.log((0, console_chars_1.createDivider)(80, "heavy"));
|
|
1270
|
+
console.log(`Errors: ${summary.errors} | Warnings: ${summary.warnings} | Time: ${(totalDuration / 1000).toFixed(1)}s`);
|
|
1271
|
+
if (summary.errors === 0)
|
|
1272
|
+
console.log(`\n${console_chars_1.emoji.success} UI LAYOUT PASSED`);
|
|
1273
|
+
else
|
|
1274
|
+
console.log(`\n${console_chars_1.emoji.error} UI LAYOUT FAILED - ${summary.errors} error(s)`);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
exports.UILayoutPreflightModule = UILayoutPreflightModule;
|
|
1278
|
+
async function main() {
|
|
1279
|
+
const reporter = (0, universal_progress_reporter_1.createUniversalProgressReporter)(path.basename(__filename, ".ts"));
|
|
1280
|
+
const args = process.argv.slice(2);
|
|
1281
|
+
const mode = args[0] || "all";
|
|
1282
|
+
const verbose = args.includes("--verbose") || args.includes("-v");
|
|
1283
|
+
const parallel = args.includes("--parallel") || args.includes("-p");
|
|
1284
|
+
const module = new UILayoutPreflightModule({ verbose, parallel });
|
|
1285
|
+
const runSingle = async (name, fn) => {
|
|
1286
|
+
const check = await fn();
|
|
1287
|
+
// Print issues for single check mode
|
|
1288
|
+
if (check.issues.length > 0) {
|
|
1289
|
+
console.log(`\n${console_chars_1.emoji.clipboard} ${check.name} Issues (${check.issues.length}):`);
|
|
1290
|
+
console.log((0, console_chars_1.createDivider)(80, "heavy"));
|
|
1291
|
+
check.issues.forEach((issue, i) => {
|
|
1292
|
+
console.log(`${i + 1}. ${issue.file}:${issue.line}`);
|
|
1293
|
+
console.log(` ${issue.severity.toUpperCase()}: ${issue.message}`);
|
|
1294
|
+
if (issue.suggestion)
|
|
1295
|
+
console.log(` ${console_chars_1.emoji.hint} ${issue.suggestion}`);
|
|
1296
|
+
if (issue.snippet)
|
|
1297
|
+
console.log(` ${console_chars_1.emoji.memo} ${issue.snippet}`);
|
|
1298
|
+
console.log();
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
1301
|
+
else {
|
|
1302
|
+
console.log(`\n${console_chars_1.emoji.success} ${check.name}: No issues found`);
|
|
1303
|
+
}
|
|
1304
|
+
return {
|
|
1305
|
+
module: `ui-layout:${name}`,
|
|
1306
|
+
passed: check.passed,
|
|
1307
|
+
totalDuration: check.duration,
|
|
1308
|
+
checks: [check],
|
|
1309
|
+
summary: {
|
|
1310
|
+
total: 1,
|
|
1311
|
+
passed: check.passed ? 1 : 0,
|
|
1312
|
+
failed: check.passed ? 0 : 1,
|
|
1313
|
+
errors: check.issues.filter((i) => i.severity === "error").length,
|
|
1314
|
+
warnings: check.issues.filter((i) => i.severity === "warning").length,
|
|
1315
|
+
},
|
|
1316
|
+
};
|
|
1317
|
+
};
|
|
1318
|
+
let result;
|
|
1319
|
+
switch (mode) {
|
|
1320
|
+
case "templates":
|
|
1321
|
+
result = await runSingle("templates", () => module.checkPageTemplates());
|
|
1322
|
+
break;
|
|
1323
|
+
case "containers":
|
|
1324
|
+
result = await runSingle("containers", () => module.checkContainerSpacing());
|
|
1325
|
+
break;
|
|
1326
|
+
case "centering":
|
|
1327
|
+
result = await runSingle("centering", () => module.checkContainerCentering());
|
|
1328
|
+
break;
|
|
1329
|
+
case "page-centering":
|
|
1330
|
+
result = await runSingle("page-centering", () => module.checkPageContentCentering());
|
|
1331
|
+
break;
|
|
1332
|
+
case "page-width":
|
|
1333
|
+
result = await runSingle("page-width", () => module.checkPageContainerWidthConsistency());
|
|
1334
|
+
break;
|
|
1335
|
+
case "header-content":
|
|
1336
|
+
result = await runSingle("header-content", () => module.checkHeaderContentSpacing());
|
|
1337
|
+
break;
|
|
1338
|
+
case "sections":
|
|
1339
|
+
result = await runSingle("sections", () => module.checkSectionSpacing());
|
|
1340
|
+
break;
|
|
1341
|
+
case "excessive":
|
|
1342
|
+
result = await runSingle("excessive", () => module.checkExcessiveSpacing());
|
|
1343
|
+
break;
|
|
1344
|
+
case "sidebar":
|
|
1345
|
+
result = await runSingle("sidebar", () => module.checkSidebarMaxWidth());
|
|
1346
|
+
break;
|
|
1347
|
+
case "filters":
|
|
1348
|
+
result = await runSingle("filters", () => module.checkFilterCardLayout());
|
|
1349
|
+
break;
|
|
1350
|
+
case "filter-card":
|
|
1351
|
+
result = await runSingle("filter-card", () => module.checkFilterSectionInCard());
|
|
1352
|
+
break;
|
|
1353
|
+
case "wrappers":
|
|
1354
|
+
result = await runSingle("wrappers", () => module.checkContentWrappers());
|
|
1355
|
+
break;
|
|
1356
|
+
case "breadcrumb-gap":
|
|
1357
|
+
result = await runSingle("breadcrumb-gap", () => module.checkBreadcrumbGap());
|
|
1358
|
+
break;
|
|
1359
|
+
case "content-padding":
|
|
1360
|
+
result = await runSingle("content-padding", () => module.checkContentAreaPaddingConsistency());
|
|
1361
|
+
break;
|
|
1362
|
+
default:
|
|
1363
|
+
result = await module.runAll();
|
|
1364
|
+
break;
|
|
1365
|
+
}
|
|
1366
|
+
process.exit(result.passed ? 0 : 1);
|
|
1367
|
+
}
|
|
1368
|
+
if (require.main === module) {
|
|
1369
|
+
main();
|
|
1370
|
+
}
|
|
1371
|
+
//# sourceMappingURL=ui-layout.js.map
|