driftdetect-detectors 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accessibility/alt-text.d.ts +63 -0
- package/dist/accessibility/alt-text.d.ts.map +1 -0
- package/dist/accessibility/alt-text.js +100 -0
- package/dist/accessibility/alt-text.js.map +1 -0
- package/dist/accessibility/aria-roles.d.ts +65 -0
- package/dist/accessibility/aria-roles.d.ts.map +1 -0
- package/dist/accessibility/aria-roles.js +87 -0
- package/dist/accessibility/aria-roles.js.map +1 -0
- package/dist/accessibility/focus-management.d.ts +62 -0
- package/dist/accessibility/focus-management.d.ts.map +1 -0
- package/dist/accessibility/focus-management.js +88 -0
- package/dist/accessibility/focus-management.js.map +1 -0
- package/dist/accessibility/heading-hierarchy.d.ts +66 -0
- package/dist/accessibility/heading-hierarchy.d.ts.map +1 -0
- package/dist/accessibility/heading-hierarchy.js +94 -0
- package/dist/accessibility/heading-hierarchy.js.map +1 -0
- package/dist/accessibility/index.d.ts +25 -0
- package/dist/accessibility/index.d.ts.map +1 -0
- package/dist/accessibility/index.js +21 -0
- package/dist/accessibility/index.js.map +1 -0
- package/dist/accessibility/keyboard-nav.d.ts +63 -0
- package/dist/accessibility/keyboard-nav.d.ts.map +1 -0
- package/dist/accessibility/keyboard-nav.js +86 -0
- package/dist/accessibility/keyboard-nav.js.map +1 -0
- package/dist/accessibility/semantic-html.d.ts +76 -0
- package/dist/accessibility/semantic-html.d.ts.map +1 -0
- package/dist/accessibility/semantic-html.js +204 -0
- package/dist/accessibility/semantic-html.js.map +1 -0
- package/dist/api/client-patterns.d.ts +121 -0
- package/dist/api/client-patterns.d.ts.map +1 -0
- package/dist/api/client-patterns.js +478 -0
- package/dist/api/client-patterns.js.map +1 -0
- package/dist/api/error-format.d.ts +140 -0
- package/dist/api/error-format.d.ts.map +1 -0
- package/dist/api/error-format.js +614 -0
- package/dist/api/error-format.js.map +1 -0
- package/dist/api/http-methods.d.ts +255 -0
- package/dist/api/http-methods.d.ts.map +1 -0
- package/dist/api/http-methods.js +890 -0
- package/dist/api/http-methods.js.map +1 -0
- package/dist/api/index.d.ts +16 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +37 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/pagination.d.ts +133 -0
- package/dist/api/pagination.d.ts.map +1 -0
- package/dist/api/pagination.js +521 -0
- package/dist/api/pagination.js.map +1 -0
- package/dist/api/response-envelope.d.ts +261 -0
- package/dist/api/response-envelope.d.ts.map +1 -0
- package/dist/api/response-envelope.js +1050 -0
- package/dist/api/response-envelope.js.map +1 -0
- package/dist/api/retry-patterns.d.ts +117 -0
- package/dist/api/retry-patterns.d.ts.map +1 -0
- package/dist/api/retry-patterns.js +480 -0
- package/dist/api/retry-patterns.js.map +1 -0
- package/dist/api/route-structure.d.ts +128 -0
- package/dist/api/route-structure.d.ts.map +1 -0
- package/dist/api/route-structure.js +738 -0
- package/dist/api/route-structure.js.map +1 -0
- package/dist/auth/audit-logging.d.ts +80 -0
- package/dist/auth/audit-logging.d.ts.map +1 -0
- package/dist/auth/audit-logging.js +370 -0
- package/dist/auth/audit-logging.js.map +1 -0
- package/dist/auth/index.d.ts +33 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +49 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/middleware-usage.d.ts +65 -0
- package/dist/auth/middleware-usage.d.ts.map +1 -0
- package/dist/auth/middleware-usage.js +192 -0
- package/dist/auth/middleware-usage.js.map +1 -0
- package/dist/auth/permission-checks.d.ts +60 -0
- package/dist/auth/permission-checks.d.ts.map +1 -0
- package/dist/auth/permission-checks.js +159 -0
- package/dist/auth/permission-checks.js.map +1 -0
- package/dist/auth/rbac-patterns.d.ts +68 -0
- package/dist/auth/rbac-patterns.d.ts.map +1 -0
- package/dist/auth/rbac-patterns.js +143 -0
- package/dist/auth/rbac-patterns.js.map +1 -0
- package/dist/auth/resource-ownership.d.ts +77 -0
- package/dist/auth/resource-ownership.d.ts.map +1 -0
- package/dist/auth/resource-ownership.js +324 -0
- package/dist/auth/resource-ownership.js.map +1 -0
- package/dist/auth/token-handling.d.ts +64 -0
- package/dist/auth/token-handling.d.ts.map +1 -0
- package/dist/auth/token-handling.js +151 -0
- package/dist/auth/token-handling.js.map +1 -0
- package/dist/base/ast-detector.d.ts +421 -0
- package/dist/base/ast-detector.d.ts.map +1 -0
- package/dist/base/ast-detector.js +699 -0
- package/dist/base/ast-detector.js.map +1 -0
- package/dist/base/base-detector.d.ts +366 -0
- package/dist/base/base-detector.d.ts.map +1 -0
- package/dist/base/base-detector.js +170 -0
- package/dist/base/base-detector.js.map +1 -0
- package/dist/base/index.d.ts +12 -0
- package/dist/base/index.d.ts.map +1 -0
- package/dist/base/index.js +17 -0
- package/dist/base/index.js.map +1 -0
- package/dist/base/regex-detector.d.ts +421 -0
- package/dist/base/regex-detector.d.ts.map +1 -0
- package/dist/base/regex-detector.js +537 -0
- package/dist/base/regex-detector.js.map +1 -0
- package/dist/base/structural-detector.d.ts +424 -0
- package/dist/base/structural-detector.d.ts.map +1 -0
- package/dist/base/structural-detector.js +731 -0
- package/dist/base/structural-detector.js.map +1 -0
- package/dist/base/types.d.ts +53 -0
- package/dist/base/types.d.ts.map +1 -0
- package/dist/base/types.js +5 -0
- package/dist/base/types.js.map +1 -0
- package/dist/components/component-structure.d.ts +163 -0
- package/dist/components/component-structure.d.ts.map +1 -0
- package/dist/components/component-structure.js +500 -0
- package/dist/components/component-structure.js.map +1 -0
- package/dist/components/composition.d.ts +287 -0
- package/dist/components/composition.d.ts.map +1 -0
- package/dist/components/composition.js +1123 -0
- package/dist/components/composition.js.map +1 -0
- package/dist/components/duplicate-detection.d.ts +251 -0
- package/dist/components/duplicate-detection.d.ts.map +1 -0
- package/dist/components/duplicate-detection.js +804 -0
- package/dist/components/duplicate-detection.js.map +1 -0
- package/dist/components/index.d.ts +16 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +51 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/near-duplicate.d.ts +402 -0
- package/dist/components/near-duplicate.d.ts.map +1 -0
- package/dist/components/near-duplicate.js +1090 -0
- package/dist/components/near-duplicate.js.map +1 -0
- package/dist/components/props-patterns.d.ts +194 -0
- package/dist/components/props-patterns.d.ts.map +1 -0
- package/dist/components/props-patterns.js +795 -0
- package/dist/components/props-patterns.js.map +1 -0
- package/dist/components/ref-forwarding.d.ts +250 -0
- package/dist/components/ref-forwarding.d.ts.map +1 -0
- package/dist/components/ref-forwarding.js +832 -0
- package/dist/components/ref-forwarding.js.map +1 -0
- package/dist/components/state-patterns.d.ts +291 -0
- package/dist/components/state-patterns.d.ts.map +1 -0
- package/dist/components/state-patterns.js +970 -0
- package/dist/components/state-patterns.js.map +1 -0
- package/dist/config/config-validation.d.ts +74 -0
- package/dist/config/config-validation.d.ts.map +1 -0
- package/dist/config/config-validation.js +446 -0
- package/dist/config/config-validation.js.map +1 -0
- package/dist/config/default-values.d.ts +72 -0
- package/dist/config/default-values.d.ts.map +1 -0
- package/dist/config/default-values.js +386 -0
- package/dist/config/default-values.js.map +1 -0
- package/dist/config/env-naming.d.ts +73 -0
- package/dist/config/env-naming.d.ts.map +1 -0
- package/dist/config/env-naming.js +429 -0
- package/dist/config/env-naming.js.map +1 -0
- package/dist/config/environment-detection.d.ts +72 -0
- package/dist/config/environment-detection.d.ts.map +1 -0
- package/dist/config/environment-detection.js +400 -0
- package/dist/config/environment-detection.js.map +1 -0
- package/dist/config/feature-flags.d.ts +72 -0
- package/dist/config/feature-flags.d.ts.map +1 -0
- package/dist/config/feature-flags.js +384 -0
- package/dist/config/feature-flags.js.map +1 -0
- package/dist/config/index.d.ts +27 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +43 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/required-optional.d.ts +71 -0
- package/dist/config/required-optional.d.ts.map +1 -0
- package/dist/config/required-optional.js +344 -0
- package/dist/config/required-optional.js.map +1 -0
- package/dist/data-access/connection-pooling.d.ts +63 -0
- package/dist/data-access/connection-pooling.d.ts.map +1 -0
- package/dist/data-access/connection-pooling.js +297 -0
- package/dist/data-access/connection-pooling.js.map +1 -0
- package/dist/data-access/dto-patterns.d.ts +64 -0
- package/dist/data-access/dto-patterns.d.ts.map +1 -0
- package/dist/data-access/dto-patterns.js +291 -0
- package/dist/data-access/dto-patterns.js.map +1 -0
- package/dist/data-access/index.d.ts +31 -0
- package/dist/data-access/index.d.ts.map +1 -0
- package/dist/data-access/index.js +49 -0
- package/dist/data-access/index.js.map +1 -0
- package/dist/data-access/n-plus-one.d.ts +60 -0
- package/dist/data-access/n-plus-one.d.ts.map +1 -0
- package/dist/data-access/n-plus-one.js +264 -0
- package/dist/data-access/n-plus-one.js.map +1 -0
- package/dist/data-access/query-patterns.d.ts +64 -0
- package/dist/data-access/query-patterns.d.ts.map +1 -0
- package/dist/data-access/query-patterns.js +314 -0
- package/dist/data-access/query-patterns.js.map +1 -0
- package/dist/data-access/repository-pattern.d.ts +62 -0
- package/dist/data-access/repository-pattern.d.ts.map +1 -0
- package/dist/data-access/repository-pattern.js +257 -0
- package/dist/data-access/repository-pattern.js.map +1 -0
- package/dist/data-access/transaction-patterns.d.ts +61 -0
- package/dist/data-access/transaction-patterns.d.ts.map +1 -0
- package/dist/data-access/transaction-patterns.js +277 -0
- package/dist/data-access/transaction-patterns.js.map +1 -0
- package/dist/data-access/validation-patterns.d.ts +62 -0
- package/dist/data-access/validation-patterns.d.ts.map +1 -0
- package/dist/data-access/validation-patterns.js +301 -0
- package/dist/data-access/validation-patterns.js.map +1 -0
- package/dist/documentation/deprecation.d.ts +62 -0
- package/dist/documentation/deprecation.d.ts.map +1 -0
- package/dist/documentation/deprecation.js +83 -0
- package/dist/documentation/deprecation.js.map +1 -0
- package/dist/documentation/example-code.d.ts +64 -0
- package/dist/documentation/example-code.d.ts.map +1 -0
- package/dist/documentation/example-code.js +79 -0
- package/dist/documentation/example-code.js.map +1 -0
- package/dist/documentation/index.d.ts +22 -0
- package/dist/documentation/index.d.ts.map +1 -0
- package/dist/documentation/index.js +19 -0
- package/dist/documentation/index.js.map +1 -0
- package/dist/documentation/jsdoc-patterns.d.ts +72 -0
- package/dist/documentation/jsdoc-patterns.d.ts.map +1 -0
- package/dist/documentation/jsdoc-patterns.js +92 -0
- package/dist/documentation/jsdoc-patterns.js.map +1 -0
- package/dist/documentation/readme-structure.d.ts +67 -0
- package/dist/documentation/readme-structure.d.ts.map +1 -0
- package/dist/documentation/readme-structure.js +76 -0
- package/dist/documentation/readme-structure.js.map +1 -0
- package/dist/documentation/todo-patterns.d.ts +67 -0
- package/dist/documentation/todo-patterns.d.ts.map +1 -0
- package/dist/documentation/todo-patterns.js +73 -0
- package/dist/documentation/todo-patterns.js.map +1 -0
- package/dist/errors/async-errors.d.ts +72 -0
- package/dist/errors/async-errors.d.ts.map +1 -0
- package/dist/errors/async-errors.js +214 -0
- package/dist/errors/async-errors.js.map +1 -0
- package/dist/errors/circuit-breaker.d.ts +53 -0
- package/dist/errors/circuit-breaker.d.ts.map +1 -0
- package/dist/errors/circuit-breaker.js +241 -0
- package/dist/errors/circuit-breaker.js.map +1 -0
- package/dist/errors/error-codes.d.ts +73 -0
- package/dist/errors/error-codes.d.ts.map +1 -0
- package/dist/errors/error-codes.js +211 -0
- package/dist/errors/error-codes.js.map +1 -0
- package/dist/errors/error-logging.d.ts +73 -0
- package/dist/errors/error-logging.d.ts.map +1 -0
- package/dist/errors/error-logging.js +256 -0
- package/dist/errors/error-logging.js.map +1 -0
- package/dist/errors/error-propagation.d.ts +73 -0
- package/dist/errors/error-propagation.d.ts.map +1 -0
- package/dist/errors/error-propagation.js +244 -0
- package/dist/errors/error-propagation.js.map +1 -0
- package/dist/errors/exception-hierarchy.d.ts +75 -0
- package/dist/errors/exception-hierarchy.d.ts.map +1 -0
- package/dist/errors/exception-hierarchy.js +259 -0
- package/dist/errors/exception-hierarchy.js.map +1 -0
- package/dist/errors/index.d.ts +31 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +49 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/try-catch-placement.d.ts +73 -0
- package/dist/errors/try-catch-placement.d.ts.map +1 -0
- package/dist/errors/try-catch-placement.js +214 -0
- package/dist/errors/try-catch-placement.js.map +1 -0
- package/dist/index.d.ts +221 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +245 -0
- package/dist/index.js.map +1 -0
- package/dist/logging/context-fields.d.ts +48 -0
- package/dist/logging/context-fields.d.ts.map +1 -0
- package/dist/logging/context-fields.js +160 -0
- package/dist/logging/context-fields.js.map +1 -0
- package/dist/logging/correlation-ids.d.ts +44 -0
- package/dist/logging/correlation-ids.d.ts.map +1 -0
- package/dist/logging/correlation-ids.js +144 -0
- package/dist/logging/correlation-ids.js.map +1 -0
- package/dist/logging/health-checks.d.ts +45 -0
- package/dist/logging/health-checks.d.ts.map +1 -0
- package/dist/logging/health-checks.js +165 -0
- package/dist/logging/health-checks.js.map +1 -0
- package/dist/logging/index.d.ts +31 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +49 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/log-levels.d.ts +46 -0
- package/dist/logging/log-levels.d.ts.map +1 -0
- package/dist/logging/log-levels.js +178 -0
- package/dist/logging/log-levels.js.map +1 -0
- package/dist/logging/metric-naming.d.ts +46 -0
- package/dist/logging/metric-naming.d.ts.map +1 -0
- package/dist/logging/metric-naming.js +157 -0
- package/dist/logging/metric-naming.js.map +1 -0
- package/dist/logging/pii-redaction.d.ts +44 -0
- package/dist/logging/pii-redaction.d.ts.map +1 -0
- package/dist/logging/pii-redaction.js +166 -0
- package/dist/logging/pii-redaction.js.map +1 -0
- package/dist/logging/structured-format.d.ts +53 -0
- package/dist/logging/structured-format.d.ts.map +1 -0
- package/dist/logging/structured-format.js +235 -0
- package/dist/logging/structured-format.js.map +1 -0
- package/dist/performance/bundle-size.d.ts +79 -0
- package/dist/performance/bundle-size.d.ts.map +1 -0
- package/dist/performance/bundle-size.js +276 -0
- package/dist/performance/bundle-size.js.map +1 -0
- package/dist/performance/caching-patterns.d.ts +78 -0
- package/dist/performance/caching-patterns.d.ts.map +1 -0
- package/dist/performance/caching-patterns.js +257 -0
- package/dist/performance/caching-patterns.js.map +1 -0
- package/dist/performance/code-splitting.d.ts +86 -0
- package/dist/performance/code-splitting.d.ts.map +1 -0
- package/dist/performance/code-splitting.js +447 -0
- package/dist/performance/code-splitting.js.map +1 -0
- package/dist/performance/debounce-throttle.d.ts +75 -0
- package/dist/performance/debounce-throttle.d.ts.map +1 -0
- package/dist/performance/debounce-throttle.js +232 -0
- package/dist/performance/debounce-throttle.js.map +1 -0
- package/dist/performance/index.d.ts +28 -0
- package/dist/performance/index.d.ts.map +1 -0
- package/dist/performance/index.js +39 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/performance/lazy-loading.d.ts +75 -0
- package/dist/performance/lazy-loading.d.ts.map +1 -0
- package/dist/performance/lazy-loading.js +233 -0
- package/dist/performance/lazy-loading.js.map +1 -0
- package/dist/performance/memoization.d.ts +75 -0
- package/dist/performance/memoization.d.ts.map +1 -0
- package/dist/performance/memoization.js +251 -0
- package/dist/performance/memoization.js.map +1 -0
- package/dist/registry/detector-registry.d.ts +266 -0
- package/dist/registry/detector-registry.d.ts.map +1 -0
- package/dist/registry/detector-registry.js +526 -0
- package/dist/registry/detector-registry.js.map +1 -0
- package/dist/registry/index.d.ts +10 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +10 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/loader.d.ts +232 -0
- package/dist/registry/loader.d.ts.map +1 -0
- package/dist/registry/loader.js +419 -0
- package/dist/registry/loader.js.map +1 -0
- package/dist/registry/types.d.ts +111 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/registry/types.js +19 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/security/csp-headers.d.ts +78 -0
- package/dist/security/csp-headers.d.ts.map +1 -0
- package/dist/security/csp-headers.js +401 -0
- package/dist/security/csp-headers.js.map +1 -0
- package/dist/security/csrf-protection.d.ts +72 -0
- package/dist/security/csrf-protection.d.ts.map +1 -0
- package/dist/security/csrf-protection.js +344 -0
- package/dist/security/csrf-protection.js.map +1 -0
- package/dist/security/index.d.ts +30 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +48 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/input-sanitization.d.ts +74 -0
- package/dist/security/input-sanitization.d.ts.map +1 -0
- package/dist/security/input-sanitization.js +373 -0
- package/dist/security/input-sanitization.js.map +1 -0
- package/dist/security/rate-limiting.d.ts +81 -0
- package/dist/security/rate-limiting.d.ts.map +1 -0
- package/dist/security/rate-limiting.js +535 -0
- package/dist/security/rate-limiting.js.map +1 -0
- package/dist/security/secret-management.d.ts +83 -0
- package/dist/security/secret-management.d.ts.map +1 -0
- package/dist/security/secret-management.js +547 -0
- package/dist/security/secret-management.js.map +1 -0
- package/dist/security/sql-injection.d.ts +76 -0
- package/dist/security/sql-injection.d.ts.map +1 -0
- package/dist/security/sql-injection.js +383 -0
- package/dist/security/sql-injection.js.map +1 -0
- package/dist/security/xss-prevention.d.ts +80 -0
- package/dist/security/xss-prevention.d.ts.map +1 -0
- package/dist/security/xss-prevention.js +416 -0
- package/dist/security/xss-prevention.js.map +1 -0
- package/dist/structural/barrel-exports.d.ts +178 -0
- package/dist/structural/barrel-exports.d.ts.map +1 -0
- package/dist/structural/barrel-exports.js +553 -0
- package/dist/structural/barrel-exports.js.map +1 -0
- package/dist/structural/circular-deps.d.ts +140 -0
- package/dist/structural/circular-deps.d.ts.map +1 -0
- package/dist/structural/circular-deps.js +422 -0
- package/dist/structural/circular-deps.js.map +1 -0
- package/dist/structural/co-location.d.ts +202 -0
- package/dist/structural/co-location.d.ts.map +1 -0
- package/dist/structural/co-location.js +640 -0
- package/dist/structural/co-location.js.map +1 -0
- package/dist/structural/directory-structure.d.ts +151 -0
- package/dist/structural/directory-structure.d.ts.map +1 -0
- package/dist/structural/directory-structure.js +457 -0
- package/dist/structural/directory-structure.js.map +1 -0
- package/dist/structural/file-naming.d.ts +61 -0
- package/dist/structural/file-naming.d.ts.map +1 -0
- package/dist/structural/file-naming.js +231 -0
- package/dist/structural/file-naming.js.map +1 -0
- package/dist/structural/import-ordering.d.ts +212 -0
- package/dist/structural/import-ordering.d.ts.map +1 -0
- package/dist/structural/import-ordering.js +821 -0
- package/dist/structural/import-ordering.js.map +1 -0
- package/dist/structural/index.d.ts +23 -0
- package/dist/structural/index.d.ts.map +1 -0
- package/dist/structural/index.js +26 -0
- package/dist/structural/index.js.map +1 -0
- package/dist/structural/module-boundaries.d.ts +164 -0
- package/dist/structural/module-boundaries.d.ts.map +1 -0
- package/dist/structural/module-boundaries.js +616 -0
- package/dist/structural/module-boundaries.js.map +1 -0
- package/dist/structural/package-boundaries.d.ts +182 -0
- package/dist/structural/package-boundaries.d.ts.map +1 -0
- package/dist/structural/package-boundaries.js +602 -0
- package/dist/structural/package-boundaries.js.map +1 -0
- package/dist/styling/class-naming.d.ts +263 -0
- package/dist/styling/class-naming.d.ts.map +1 -0
- package/dist/styling/class-naming.js +892 -0
- package/dist/styling/class-naming.js.map +1 -0
- package/dist/styling/color-usage.d.ts +213 -0
- package/dist/styling/color-usage.d.ts.map +1 -0
- package/dist/styling/color-usage.js +732 -0
- package/dist/styling/color-usage.js.map +1 -0
- package/dist/styling/design-tokens.d.ts +212 -0
- package/dist/styling/design-tokens.d.ts.map +1 -0
- package/dist/styling/design-tokens.js +748 -0
- package/dist/styling/design-tokens.js.map +1 -0
- package/dist/styling/index.d.ts +16 -0
- package/dist/styling/index.d.ts.map +1 -0
- package/dist/styling/index.js +56 -0
- package/dist/styling/index.js.map +1 -0
- package/dist/styling/responsive.d.ts +304 -0
- package/dist/styling/responsive.d.ts.map +1 -0
- package/dist/styling/responsive.js +888 -0
- package/dist/styling/responsive.js.map +1 -0
- package/dist/styling/spacing-scale.d.ts +248 -0
- package/dist/styling/spacing-scale.d.ts.map +1 -0
- package/dist/styling/spacing-scale.js +865 -0
- package/dist/styling/spacing-scale.js.map +1 -0
- package/dist/styling/tailwind-patterns.d.ts +305 -0
- package/dist/styling/tailwind-patterns.d.ts.map +1 -0
- package/dist/styling/tailwind-patterns.js +1181 -0
- package/dist/styling/tailwind-patterns.js.map +1 -0
- package/dist/styling/typography.d.ts +281 -0
- package/dist/styling/typography.d.ts.map +1 -0
- package/dist/styling/typography.js +1004 -0
- package/dist/styling/typography.js.map +1 -0
- package/dist/styling/z-index-scale.d.ts +270 -0
- package/dist/styling/z-index-scale.d.ts.map +1 -0
- package/dist/styling/z-index-scale.js +714 -0
- package/dist/styling/z-index-scale.js.map +1 -0
- package/dist/testing/co-location.d.ts +42 -0
- package/dist/testing/co-location.d.ts.map +1 -0
- package/dist/testing/co-location.js +134 -0
- package/dist/testing/co-location.js.map +1 -0
- package/dist/testing/describe-naming.d.ts +47 -0
- package/dist/testing/describe-naming.d.ts.map +1 -0
- package/dist/testing/describe-naming.js +150 -0
- package/dist/testing/describe-naming.js.map +1 -0
- package/dist/testing/file-naming.d.ts +44 -0
- package/dist/testing/file-naming.d.ts.map +1 -0
- package/dist/testing/file-naming.js +131 -0
- package/dist/testing/file-naming.js.map +1 -0
- package/dist/testing/fixture-patterns.d.ts +52 -0
- package/dist/testing/fixture-patterns.d.ts.map +1 -0
- package/dist/testing/fixture-patterns.js +228 -0
- package/dist/testing/fixture-patterns.js.map +1 -0
- package/dist/testing/index.d.ts +31 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +49 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/mock-patterns.d.ts +53 -0
- package/dist/testing/mock-patterns.d.ts.map +1 -0
- package/dist/testing/mock-patterns.js +264 -0
- package/dist/testing/mock-patterns.js.map +1 -0
- package/dist/testing/setup-teardown.d.ts +55 -0
- package/dist/testing/setup-teardown.d.ts.map +1 -0
- package/dist/testing/setup-teardown.js +262 -0
- package/dist/testing/setup-teardown.js.map +1 -0
- package/dist/testing/test-structure.d.ts +51 -0
- package/dist/testing/test-structure.d.ts.map +1 -0
- package/dist/testing/test-structure.js +225 -0
- package/dist/testing/test-structure.js.map +1 -0
- package/dist/types/any-usage.d.ts +99 -0
- package/dist/types/any-usage.d.ts.map +1 -0
- package/dist/types/any-usage.js +641 -0
- package/dist/types/any-usage.js.map +1 -0
- package/dist/types/file-location.d.ts +76 -0
- package/dist/types/file-location.d.ts.map +1 -0
- package/dist/types/file-location.js +395 -0
- package/dist/types/file-location.js.map +1 -0
- package/dist/types/generic-patterns.d.ts +97 -0
- package/dist/types/generic-patterns.d.ts.map +1 -0
- package/dist/types/generic-patterns.js +615 -0
- package/dist/types/generic-patterns.js.map +1 -0
- package/dist/types/index.d.ts +31 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +43 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/interface-vs-type.d.ts +81 -0
- package/dist/types/interface-vs-type.d.ts.map +1 -0
- package/dist/types/interface-vs-type.js +440 -0
- package/dist/types/interface-vs-type.js.map +1 -0
- package/dist/types/naming-conventions.d.ts +84 -0
- package/dist/types/naming-conventions.d.ts.map +1 -0
- package/dist/types/naming-conventions.js +455 -0
- package/dist/types/naming-conventions.js.map +1 -0
- package/dist/types/type-assertions.d.ts +98 -0
- package/dist/types/type-assertions.d.ts.map +1 -0
- package/dist/types/type-assertions.js +639 -0
- package/dist/types/type-assertions.js.map +1 -0
- package/dist/types/utility-types.d.ts +110 -0
- package/dist/types/utility-types.d.ts.map +1 -0
- package/dist/types/utility-types.js +547 -0
- package/dist/types/utility-types.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,865 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spacing Scale Detector - Spacing consistency detection
|
|
3
|
+
*
|
|
4
|
+
* Detects spacing scale patterns including:
|
|
5
|
+
* - Consistent spacing values (4px increments, rem-based scales, etc.)
|
|
6
|
+
* - Tailwind spacing classes (p-4, m-2, gap-8, etc.)
|
|
7
|
+
* - CSS custom properties for spacing (--spacing-*)
|
|
8
|
+
*
|
|
9
|
+
* Flags arbitrary spacing values:
|
|
10
|
+
* - Values that don't fit the detected scale (e.g., 13px, 17px)
|
|
11
|
+
* - Inconsistent units (mixing px and rem)
|
|
12
|
+
*
|
|
13
|
+
* @requirements 9.2 - THE Styling_Detector SHALL detect spacing scale adherence (p-4 vs arbitrary values)
|
|
14
|
+
*/
|
|
15
|
+
import { RegexDetector } from '../base/index.js';
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Constants
|
|
18
|
+
// ============================================================================
|
|
19
|
+
/**
|
|
20
|
+
* Standard 4px-based spacing scale values
|
|
21
|
+
*/
|
|
22
|
+
export const SPACING_SCALE_4PX = [0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 48, 56, 64, 72, 80, 96];
|
|
23
|
+
/**
|
|
24
|
+
* Standard 8px-based spacing scale values
|
|
25
|
+
*/
|
|
26
|
+
export const SPACING_SCALE_8PX = [0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 96, 112, 128];
|
|
27
|
+
/**
|
|
28
|
+
* Standard rem-based spacing scale values (Tailwind-like)
|
|
29
|
+
*/
|
|
30
|
+
export const SPACING_SCALE_REM = [0, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16];
|
|
31
|
+
/**
|
|
32
|
+
* Tailwind spacing class patterns
|
|
33
|
+
*/
|
|
34
|
+
export const TAILWIND_SPACING_PATTERNS = [
|
|
35
|
+
// Padding classes: p-4, px-2, py-8, pt-4, pr-2, pb-6, pl-3
|
|
36
|
+
/\b(?:p|px|py|pt|pr|pb|pl)-(\d+(?:\.\d+)?)\b/g,
|
|
37
|
+
// Margin classes: m-4, mx-2, my-8, mt-4, mr-2, mb-6, ml-3
|
|
38
|
+
/\b(?:m|mx|my|mt|mr|mb|ml)-(\d+(?:\.\d+)?)\b/g,
|
|
39
|
+
// Gap classes: gap-4, gap-x-2, gap-y-8
|
|
40
|
+
/\bgap(?:-[xy])?-(\d+(?:\.\d+)?)\b/g,
|
|
41
|
+
// Space classes: space-x-4, space-y-2
|
|
42
|
+
/\bspace-[xy]-(\d+(?:\.\d+)?)\b/g,
|
|
43
|
+
// Width/height spacing: w-4, h-8, size-4
|
|
44
|
+
/\b(?:w|h|size)-(\d+(?:\.\d+)?)\b/g,
|
|
45
|
+
// Inset classes: inset-4, inset-x-2, top-4, right-2, bottom-6, left-3
|
|
46
|
+
/\b(?:inset|inset-[xy]|top|right|bottom|left)-(\d+(?:\.\d+)?)\b/g,
|
|
47
|
+
];
|
|
48
|
+
/**
|
|
49
|
+
* Tailwind arbitrary spacing value patterns (e.g., p-[13px], m-[1.5rem])
|
|
50
|
+
*/
|
|
51
|
+
export const TAILWIND_ARBITRARY_SPACING_PATTERN = /\b(?:p|px|py|pt|pr|pb|pl|m|mx|my|mt|mr|mb|ml|gap|gap-[xy]|space-[xy]|w|h|size|inset|inset-[xy]|top|right|bottom|left)-\[([^\]]+)\]/g;
|
|
52
|
+
/**
|
|
53
|
+
* CSS custom property patterns for spacing
|
|
54
|
+
*/
|
|
55
|
+
export const CSS_SPACING_PROPERTY_PATTERN = /var\(\s*--(?:spacing|space|gap|margin|padding)[-_]?([a-zA-Z0-9_-]*)\s*(?:,\s*[^)]+)?\)/g;
|
|
56
|
+
/**
|
|
57
|
+
* Theme spacing object patterns
|
|
58
|
+
*/
|
|
59
|
+
export const THEME_SPACING_PATTERNS = [
|
|
60
|
+
// theme.spacing.*, theme.space.*
|
|
61
|
+
/theme\.(?:spacing|space)\.([a-zA-Z0-9_.[\]]+)/g,
|
|
62
|
+
// ${theme.spacing.*} in template literals
|
|
63
|
+
/\$\{theme\.(?:spacing|space)\.([a-zA-Z0-9_.[\]]+)\}/g,
|
|
64
|
+
// props.theme.spacing.*
|
|
65
|
+
/props\.theme\.(?:spacing|space)\.([a-zA-Z0-9_.[\]]+)/g,
|
|
66
|
+
];
|
|
67
|
+
/**
|
|
68
|
+
* Hardcoded spacing value patterns
|
|
69
|
+
*/
|
|
70
|
+
export const HARDCODED_SPACING_PATTERNS = {
|
|
71
|
+
// Pixel values: 10px, 20px (excluding 0px and 1px)
|
|
72
|
+
px: /(?<![a-zA-Z0-9_-])(\d+)px\b/g,
|
|
73
|
+
// Rem values: 1rem, 2rem
|
|
74
|
+
rem: /(?<![a-zA-Z0-9_-])(\d+(?:\.\d+)?)rem\b/g,
|
|
75
|
+
// Em values: 1em, 2em
|
|
76
|
+
em: /(?<![a-zA-Z0-9_-])(\d+(?:\.\d+)?)em\b/g,
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* CSS properties that commonly use spacing values
|
|
80
|
+
*/
|
|
81
|
+
export const SPACING_PROPERTIES = [
|
|
82
|
+
'margin',
|
|
83
|
+
'margin-top',
|
|
84
|
+
'margin-right',
|
|
85
|
+
'margin-bottom',
|
|
86
|
+
'margin-left',
|
|
87
|
+
'padding',
|
|
88
|
+
'padding-top',
|
|
89
|
+
'padding-right',
|
|
90
|
+
'padding-bottom',
|
|
91
|
+
'padding-left',
|
|
92
|
+
'gap',
|
|
93
|
+
'row-gap',
|
|
94
|
+
'column-gap',
|
|
95
|
+
'top',
|
|
96
|
+
'right',
|
|
97
|
+
'bottom',
|
|
98
|
+
'left',
|
|
99
|
+
'inset',
|
|
100
|
+
'width',
|
|
101
|
+
'height',
|
|
102
|
+
'min-width',
|
|
103
|
+
'min-height',
|
|
104
|
+
'max-width',
|
|
105
|
+
'max-height',
|
|
106
|
+
];
|
|
107
|
+
/**
|
|
108
|
+
* Allowed spacing values (common exceptions)
|
|
109
|
+
*/
|
|
110
|
+
export const ALLOWED_SPACING_VALUES = new Set([
|
|
111
|
+
'0',
|
|
112
|
+
'0px',
|
|
113
|
+
'1px',
|
|
114
|
+
'100%',
|
|
115
|
+
'auto',
|
|
116
|
+
'inherit',
|
|
117
|
+
'initial',
|
|
118
|
+
'unset',
|
|
119
|
+
'none',
|
|
120
|
+
]);
|
|
121
|
+
/**
|
|
122
|
+
* File patterns to exclude from arbitrary spacing detection
|
|
123
|
+
*/
|
|
124
|
+
export const EXCLUDED_FILE_PATTERNS = [
|
|
125
|
+
/\.test\.[jt]sx?$/,
|
|
126
|
+
/\.spec\.[jt]sx?$/,
|
|
127
|
+
/\.stories\.[jt]sx?$/,
|
|
128
|
+
/design-tokens?\//,
|
|
129
|
+
/tokens?\//,
|
|
130
|
+
/theme\//,
|
|
131
|
+
/\.config\.[jt]s$/,
|
|
132
|
+
/tailwind\.config/,
|
|
133
|
+
];
|
|
134
|
+
// ============================================================================
|
|
135
|
+
// Helper Functions
|
|
136
|
+
// ============================================================================
|
|
137
|
+
/**
|
|
138
|
+
* Check if a file should be excluded from arbitrary spacing detection
|
|
139
|
+
*/
|
|
140
|
+
export function shouldExcludeFile(filePath) {
|
|
141
|
+
return EXCLUDED_FILE_PATTERNS.some(pattern => pattern.test(filePath));
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Check if a value is in the allowed spacing values list
|
|
145
|
+
*/
|
|
146
|
+
export function isAllowedSpacingValue(value) {
|
|
147
|
+
return ALLOWED_SPACING_VALUES.has(value.toLowerCase().trim());
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Check if a pixel value is on the 4px scale
|
|
151
|
+
*/
|
|
152
|
+
export function isOn4pxScale(value) {
|
|
153
|
+
return SPACING_SCALE_4PX.includes(value);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Check if a pixel value is on the 8px scale
|
|
157
|
+
*/
|
|
158
|
+
export function isOn8pxScale(value) {
|
|
159
|
+
return SPACING_SCALE_8PX.includes(value);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Check if a rem value is on the standard rem scale
|
|
163
|
+
*/
|
|
164
|
+
export function isOnRemScale(value) {
|
|
165
|
+
return SPACING_SCALE_REM.includes(value);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Find the nearest value on the 4px scale
|
|
169
|
+
*/
|
|
170
|
+
export function findNearest4pxValue(value) {
|
|
171
|
+
let nearest = SPACING_SCALE_4PX[0];
|
|
172
|
+
let minDiff = Math.abs(value - nearest);
|
|
173
|
+
for (const scaleValue of SPACING_SCALE_4PX) {
|
|
174
|
+
const diff = Math.abs(value - scaleValue);
|
|
175
|
+
if (diff < minDiff) {
|
|
176
|
+
minDiff = diff;
|
|
177
|
+
nearest = scaleValue;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return nearest;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Find the nearest value on the 8px scale
|
|
184
|
+
*/
|
|
185
|
+
export function findNearest8pxValue(value) {
|
|
186
|
+
let nearest = SPACING_SCALE_8PX[0];
|
|
187
|
+
let minDiff = Math.abs(value - nearest);
|
|
188
|
+
for (const scaleValue of SPACING_SCALE_8PX) {
|
|
189
|
+
const diff = Math.abs(value - scaleValue);
|
|
190
|
+
if (diff < minDiff) {
|
|
191
|
+
minDiff = diff;
|
|
192
|
+
nearest = scaleValue;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return nearest;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Find the nearest value on the rem scale
|
|
199
|
+
*/
|
|
200
|
+
export function findNearestRemValue(value) {
|
|
201
|
+
let nearest = SPACING_SCALE_REM[0];
|
|
202
|
+
let minDiff = Math.abs(value - nearest);
|
|
203
|
+
for (const scaleValue of SPACING_SCALE_REM) {
|
|
204
|
+
const diff = Math.abs(value - scaleValue);
|
|
205
|
+
if (diff < minDiff) {
|
|
206
|
+
minDiff = diff;
|
|
207
|
+
nearest = scaleValue;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return nearest;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Detect Tailwind spacing classes in content
|
|
214
|
+
*/
|
|
215
|
+
export function detectTailwindSpacing(content, file) {
|
|
216
|
+
const results = [];
|
|
217
|
+
const lines = content.split('\n');
|
|
218
|
+
for (const pattern of TAILWIND_SPACING_PATTERNS) {
|
|
219
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
220
|
+
let match;
|
|
221
|
+
while ((match = regex.exec(content)) !== null) {
|
|
222
|
+
const beforeMatch = content.slice(0, match.index);
|
|
223
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
224
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
225
|
+
const column = match.index - lastNewline;
|
|
226
|
+
results.push({
|
|
227
|
+
type: 'tailwind-spacing',
|
|
228
|
+
file,
|
|
229
|
+
line: lineNumber,
|
|
230
|
+
column,
|
|
231
|
+
matchedText: match[0],
|
|
232
|
+
spacingValue: match[1] || match[0],
|
|
233
|
+
context: lines[lineNumber - 1] || '',
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return results;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Detect Tailwind arbitrary spacing values
|
|
241
|
+
*/
|
|
242
|
+
export function detectTailwindArbitrarySpacing(content, file) {
|
|
243
|
+
const results = [];
|
|
244
|
+
const lines = content.split('\n');
|
|
245
|
+
const regex = new RegExp(TAILWIND_ARBITRARY_SPACING_PATTERN.source, TAILWIND_ARBITRARY_SPACING_PATTERN.flags);
|
|
246
|
+
let match;
|
|
247
|
+
while ((match = regex.exec(content)) !== null) {
|
|
248
|
+
const value = match[1] || '';
|
|
249
|
+
// Skip allowed values
|
|
250
|
+
if (isAllowedSpacingValue(value)) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
const beforeMatch = content.slice(0, match.index);
|
|
254
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
255
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
256
|
+
const column = match.index - lastNewline;
|
|
257
|
+
const endColumn = column + match[0].length;
|
|
258
|
+
results.push({
|
|
259
|
+
type: 'tailwind-arbitrary',
|
|
260
|
+
file,
|
|
261
|
+
line: lineNumber,
|
|
262
|
+
column,
|
|
263
|
+
endLine: lineNumber,
|
|
264
|
+
endColumn,
|
|
265
|
+
value: match[0],
|
|
266
|
+
suggestedValue: suggestTailwindSpacingClass(value),
|
|
267
|
+
lineContent: lines[lineNumber - 1] || '',
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
return results;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Detect CSS custom property usage for spacing
|
|
274
|
+
*/
|
|
275
|
+
export function detectCSSSpacingProperties(content, file) {
|
|
276
|
+
const results = [];
|
|
277
|
+
const lines = content.split('\n');
|
|
278
|
+
const regex = new RegExp(CSS_SPACING_PROPERTY_PATTERN.source, CSS_SPACING_PROPERTY_PATTERN.flags);
|
|
279
|
+
let match;
|
|
280
|
+
while ((match = regex.exec(content)) !== null) {
|
|
281
|
+
const beforeMatch = content.slice(0, match.index);
|
|
282
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
283
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
284
|
+
const column = match.index - lastNewline;
|
|
285
|
+
results.push({
|
|
286
|
+
type: 'css-spacing-property',
|
|
287
|
+
file,
|
|
288
|
+
line: lineNumber,
|
|
289
|
+
column,
|
|
290
|
+
matchedText: match[0],
|
|
291
|
+
spacingValue: match[1] || '',
|
|
292
|
+
context: lines[lineNumber - 1] || '',
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
return results;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Detect theme spacing object usage
|
|
299
|
+
*/
|
|
300
|
+
export function detectThemeSpacing(content, file) {
|
|
301
|
+
const results = [];
|
|
302
|
+
const lines = content.split('\n');
|
|
303
|
+
for (const pattern of THEME_SPACING_PATTERNS) {
|
|
304
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
305
|
+
let match;
|
|
306
|
+
while ((match = regex.exec(content)) !== null) {
|
|
307
|
+
const beforeMatch = content.slice(0, match.index);
|
|
308
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
309
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
310
|
+
const column = match.index - lastNewline;
|
|
311
|
+
results.push({
|
|
312
|
+
type: 'theme-spacing',
|
|
313
|
+
file,
|
|
314
|
+
line: lineNumber,
|
|
315
|
+
column,
|
|
316
|
+
matchedText: match[0],
|
|
317
|
+
spacingValue: match[1] || match[0],
|
|
318
|
+
context: lines[lineNumber - 1] || '',
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return results;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Check if a position is inside a comment
|
|
326
|
+
*/
|
|
327
|
+
function isInsideComment(content, index) {
|
|
328
|
+
const beforeIndex = content.slice(0, index);
|
|
329
|
+
// Check for single-line comment
|
|
330
|
+
const lastNewline = beforeIndex.lastIndexOf('\n');
|
|
331
|
+
const currentLine = beforeIndex.slice(lastNewline + 1);
|
|
332
|
+
if (currentLine.includes('//')) {
|
|
333
|
+
const commentStart = currentLine.indexOf('//');
|
|
334
|
+
const positionInLine = index - lastNewline - 1;
|
|
335
|
+
if (positionInLine > commentStart) {
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// Check for multi-line comment
|
|
340
|
+
const lastBlockCommentStart = beforeIndex.lastIndexOf('/*');
|
|
341
|
+
const lastBlockCommentEnd = beforeIndex.lastIndexOf('*/');
|
|
342
|
+
if (lastBlockCommentStart > lastBlockCommentEnd) {
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
return false;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Extract CSS property name from a line
|
|
349
|
+
*/
|
|
350
|
+
function extractCSSProperty(line) {
|
|
351
|
+
// Match CSS property: property-name: value
|
|
352
|
+
const cssMatch = line.match(/([a-zA-Z-]+)\s*:/);
|
|
353
|
+
if (cssMatch && cssMatch[1]) {
|
|
354
|
+
return cssMatch[1];
|
|
355
|
+
}
|
|
356
|
+
// Match JS object property: propertyName: value
|
|
357
|
+
const jsMatch = line.match(/([a-zA-Z]+)\s*:/);
|
|
358
|
+
if (jsMatch && jsMatch[1]) {
|
|
359
|
+
// Convert camelCase to kebab-case
|
|
360
|
+
return jsMatch[1].replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
361
|
+
}
|
|
362
|
+
return undefined;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Detect arbitrary pixel spacing values
|
|
366
|
+
*/
|
|
367
|
+
export function detectArbitraryPxSpacing(content, file) {
|
|
368
|
+
const results = [];
|
|
369
|
+
const lines = content.split('\n');
|
|
370
|
+
const regex = new RegExp(HARDCODED_SPACING_PATTERNS.px.source, HARDCODED_SPACING_PATTERNS.px.flags);
|
|
371
|
+
let match;
|
|
372
|
+
while ((match = regex.exec(content)) !== null) {
|
|
373
|
+
const numValue = parseInt(match[1] || '0', 10);
|
|
374
|
+
const value = `${numValue}px`;
|
|
375
|
+
// Skip allowed values (0px, 1px)
|
|
376
|
+
if (isAllowedSpacingValue(value) || numValue <= 1) {
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
const beforeMatch = content.slice(0, match.index);
|
|
380
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
381
|
+
const lineContent = lines[lineNumber - 1] || '';
|
|
382
|
+
// Skip CSS custom property definitions
|
|
383
|
+
if (/^\s*--[a-zA-Z0-9_-]+\s*:/.test(lineContent)) {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
// Skip if inside a comment
|
|
387
|
+
if (isInsideComment(content, match.index)) {
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
// Skip if it's part of a media query breakpoint
|
|
391
|
+
if (/@media.*\(.*\d+px/.test(lineContent)) {
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
// Check if value is on a standard scale
|
|
395
|
+
const isOnScale = isOn4pxScale(numValue) || isOn8pxScale(numValue);
|
|
396
|
+
if (isOnScale) {
|
|
397
|
+
continue; // Value is on scale, not arbitrary
|
|
398
|
+
}
|
|
399
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
400
|
+
const column = match.index - lastNewline;
|
|
401
|
+
const endColumn = column + value.length;
|
|
402
|
+
const property = extractCSSProperty(lineContent);
|
|
403
|
+
const arbitraryInfo = {
|
|
404
|
+
type: 'arbitrary-px',
|
|
405
|
+
file,
|
|
406
|
+
line: lineNumber,
|
|
407
|
+
column,
|
|
408
|
+
endLine: lineNumber,
|
|
409
|
+
endColumn,
|
|
410
|
+
value,
|
|
411
|
+
suggestedValue: suggestPxSpacingValue(numValue),
|
|
412
|
+
lineContent,
|
|
413
|
+
};
|
|
414
|
+
if (property !== undefined) {
|
|
415
|
+
arbitraryInfo.property = property;
|
|
416
|
+
}
|
|
417
|
+
results.push(arbitraryInfo);
|
|
418
|
+
}
|
|
419
|
+
return results;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Detect arbitrary rem spacing values
|
|
423
|
+
*/
|
|
424
|
+
export function detectArbitraryRemSpacing(content, file) {
|
|
425
|
+
const results = [];
|
|
426
|
+
const lines = content.split('\n');
|
|
427
|
+
const regex = new RegExp(HARDCODED_SPACING_PATTERNS.rem.source, HARDCODED_SPACING_PATTERNS.rem.flags);
|
|
428
|
+
let match;
|
|
429
|
+
while ((match = regex.exec(content)) !== null) {
|
|
430
|
+
const numValue = parseFloat(match[1] || '0');
|
|
431
|
+
const value = `${numValue}rem`;
|
|
432
|
+
// Skip allowed values
|
|
433
|
+
if (isAllowedSpacingValue(value)) {
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
const beforeMatch = content.slice(0, match.index);
|
|
437
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
438
|
+
const lineContent = lines[lineNumber - 1] || '';
|
|
439
|
+
// Skip CSS custom property definitions
|
|
440
|
+
if (/^\s*--[a-zA-Z0-9_-]+\s*:/.test(lineContent)) {
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
// Skip if inside a comment
|
|
444
|
+
if (isInsideComment(content, match.index)) {
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
// Check if value is on the standard rem scale
|
|
448
|
+
if (isOnRemScale(numValue)) {
|
|
449
|
+
continue; // Value is on scale, not arbitrary
|
|
450
|
+
}
|
|
451
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
452
|
+
const column = match.index - lastNewline;
|
|
453
|
+
const endColumn = column + value.length;
|
|
454
|
+
const property = extractCSSProperty(lineContent);
|
|
455
|
+
const arbitraryInfo = {
|
|
456
|
+
type: 'arbitrary-rem',
|
|
457
|
+
file,
|
|
458
|
+
line: lineNumber,
|
|
459
|
+
column,
|
|
460
|
+
endLine: lineNumber,
|
|
461
|
+
endColumn,
|
|
462
|
+
value,
|
|
463
|
+
suggestedValue: suggestRemSpacingValue(numValue),
|
|
464
|
+
lineContent,
|
|
465
|
+
};
|
|
466
|
+
if (property !== undefined) {
|
|
467
|
+
arbitraryInfo.property = property;
|
|
468
|
+
}
|
|
469
|
+
results.push(arbitraryInfo);
|
|
470
|
+
}
|
|
471
|
+
return results;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Detect arbitrary em spacing values
|
|
475
|
+
*/
|
|
476
|
+
export function detectArbitraryEmSpacing(content, file) {
|
|
477
|
+
const results = [];
|
|
478
|
+
const lines = content.split('\n');
|
|
479
|
+
const regex = new RegExp(HARDCODED_SPACING_PATTERNS.em.source, HARDCODED_SPACING_PATTERNS.em.flags);
|
|
480
|
+
let match;
|
|
481
|
+
while ((match = regex.exec(content)) !== null) {
|
|
482
|
+
const numValue = parseFloat(match[1] || '0');
|
|
483
|
+
const value = `${numValue}em`;
|
|
484
|
+
// Skip allowed values
|
|
485
|
+
if (isAllowedSpacingValue(value)) {
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
const beforeMatch = content.slice(0, match.index);
|
|
489
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
490
|
+
const lineContent = lines[lineNumber - 1] || '';
|
|
491
|
+
// Skip CSS custom property definitions
|
|
492
|
+
if (/^\s*--[a-zA-Z0-9_-]+\s*:/.test(lineContent)) {
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
// Skip if inside a comment
|
|
496
|
+
if (isInsideComment(content, match.index)) {
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
// Check if value is on the standard rem scale (em uses same scale)
|
|
500
|
+
if (isOnRemScale(numValue)) {
|
|
501
|
+
continue; // Value is on scale, not arbitrary
|
|
502
|
+
}
|
|
503
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
504
|
+
const column = match.index - lastNewline;
|
|
505
|
+
const endColumn = column + value.length;
|
|
506
|
+
const property = extractCSSProperty(lineContent);
|
|
507
|
+
const arbitraryInfo = {
|
|
508
|
+
type: 'arbitrary-em',
|
|
509
|
+
file,
|
|
510
|
+
line: lineNumber,
|
|
511
|
+
column,
|
|
512
|
+
endLine: lineNumber,
|
|
513
|
+
endColumn,
|
|
514
|
+
value,
|
|
515
|
+
suggestedValue: suggestRemSpacingValue(numValue).replace('rem', 'em'),
|
|
516
|
+
lineContent,
|
|
517
|
+
};
|
|
518
|
+
if (property !== undefined) {
|
|
519
|
+
arbitraryInfo.property = property;
|
|
520
|
+
}
|
|
521
|
+
results.push(arbitraryInfo);
|
|
522
|
+
}
|
|
523
|
+
return results;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Suggest a Tailwind spacing class for an arbitrary value
|
|
527
|
+
*/
|
|
528
|
+
function suggestTailwindSpacingClass(value) {
|
|
529
|
+
// Extract numeric value and unit
|
|
530
|
+
const match = value.match(/^(\d+(?:\.\d+)?)(px|rem|em)?$/);
|
|
531
|
+
if (!match) {
|
|
532
|
+
return 'Use a standard Tailwind spacing class (e.g., p-4, m-2)';
|
|
533
|
+
}
|
|
534
|
+
const num = parseFloat(match[1] || '0');
|
|
535
|
+
const unit = match[2] || 'px';
|
|
536
|
+
if (unit === 'px') {
|
|
537
|
+
// Convert px to Tailwind scale (1 unit = 0.25rem = 4px)
|
|
538
|
+
const tailwindUnit = Math.round(num / 4);
|
|
539
|
+
return `Use spacing class with value ${tailwindUnit} (e.g., p-${tailwindUnit})`;
|
|
540
|
+
}
|
|
541
|
+
if (unit === 'rem') {
|
|
542
|
+
// Convert rem to Tailwind scale (1 unit = 0.25rem)
|
|
543
|
+
const tailwindUnit = Math.round(num / 0.25);
|
|
544
|
+
return `Use spacing class with value ${tailwindUnit} (e.g., p-${tailwindUnit})`;
|
|
545
|
+
}
|
|
546
|
+
return 'Use a standard Tailwind spacing class (e.g., p-4, m-2)';
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Suggest a pixel spacing value on the scale
|
|
550
|
+
*/
|
|
551
|
+
function suggestPxSpacingValue(value) {
|
|
552
|
+
const nearest4px = findNearest4pxValue(value);
|
|
553
|
+
const nearest8px = findNearest8pxValue(value);
|
|
554
|
+
// Prefer 4px scale as it's more common
|
|
555
|
+
const diff4px = Math.abs(value - nearest4px);
|
|
556
|
+
const diff8px = Math.abs(value - nearest8px);
|
|
557
|
+
if (diff4px <= diff8px) {
|
|
558
|
+
return `${nearest4px}px (4px scale) or use --spacing-${nearest4px / 4}`;
|
|
559
|
+
}
|
|
560
|
+
return `${nearest8px}px (8px scale) or use --spacing-${nearest8px / 8}`;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Suggest a rem spacing value on the scale
|
|
564
|
+
*/
|
|
565
|
+
function suggestRemSpacingValue(value) {
|
|
566
|
+
const nearest = findNearestRemValue(value);
|
|
567
|
+
return `${nearest}rem or use theme.spacing.${nearest * 4}`;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Analyze spacing scale patterns in a file
|
|
571
|
+
*/
|
|
572
|
+
export function analyzeSpacingScale(content, file) {
|
|
573
|
+
// Skip excluded files for arbitrary value detection
|
|
574
|
+
const skipArbitraryDetection = shouldExcludeFile(file);
|
|
575
|
+
// Detect spacing patterns
|
|
576
|
+
const tailwindSpacing = detectTailwindSpacing(content, file);
|
|
577
|
+
const cssSpacingProperties = detectCSSSpacingProperties(content, file);
|
|
578
|
+
const themeSpacing = detectThemeSpacing(content, file);
|
|
579
|
+
const spacingPatterns = [
|
|
580
|
+
...tailwindSpacing,
|
|
581
|
+
...cssSpacingProperties,
|
|
582
|
+
...themeSpacing,
|
|
583
|
+
];
|
|
584
|
+
// Detect arbitrary values (unless file is excluded)
|
|
585
|
+
let arbitraryValues = [];
|
|
586
|
+
if (!skipArbitraryDetection) {
|
|
587
|
+
const tailwindArbitrary = detectTailwindArbitrarySpacing(content, file);
|
|
588
|
+
const arbitraryPx = detectArbitraryPxSpacing(content, file);
|
|
589
|
+
const arbitraryRem = detectArbitraryRemSpacing(content, file);
|
|
590
|
+
const arbitraryEm = detectArbitraryEmSpacing(content, file);
|
|
591
|
+
arbitraryValues = [...tailwindArbitrary, ...arbitraryPx, ...arbitraryRem, ...arbitraryEm];
|
|
592
|
+
}
|
|
593
|
+
// Determine detected scale
|
|
594
|
+
let detectedScale = null;
|
|
595
|
+
if (tailwindSpacing.length > 0) {
|
|
596
|
+
detectedScale = 'rem'; // Tailwind uses rem-based scale
|
|
597
|
+
}
|
|
598
|
+
else if (cssSpacingProperties.length > 0 || themeSpacing.length > 0) {
|
|
599
|
+
// Could be either, default to 4px
|
|
600
|
+
detectedScale = '4px';
|
|
601
|
+
}
|
|
602
|
+
// Calculate confidence
|
|
603
|
+
const hasSpacingPatterns = spacingPatterns.length > 0;
|
|
604
|
+
const hasArbitraryValues = arbitraryValues.length > 0;
|
|
605
|
+
let scaleAdherenceConfidence = 0;
|
|
606
|
+
if (hasSpacingPatterns && !hasArbitraryValues) {
|
|
607
|
+
scaleAdherenceConfidence = 1.0;
|
|
608
|
+
}
|
|
609
|
+
else if (hasSpacingPatterns && hasArbitraryValues) {
|
|
610
|
+
const ratio = spacingPatterns.length / (spacingPatterns.length + arbitraryValues.length);
|
|
611
|
+
scaleAdherenceConfidence = ratio;
|
|
612
|
+
}
|
|
613
|
+
else if (!hasSpacingPatterns && hasArbitraryValues) {
|
|
614
|
+
scaleAdherenceConfidence = 0;
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
scaleAdherenceConfidence = 0.5; // No spacing detected
|
|
618
|
+
}
|
|
619
|
+
return {
|
|
620
|
+
spacingPatterns,
|
|
621
|
+
arbitraryValues,
|
|
622
|
+
usesTailwindSpacing: tailwindSpacing.length > 0,
|
|
623
|
+
usesCSSSpacingProperties: cssSpacingProperties.length > 0,
|
|
624
|
+
usesThemeSpacing: themeSpacing.length > 0,
|
|
625
|
+
detectedScale,
|
|
626
|
+
scaleAdherenceConfidence,
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
// ============================================================================
|
|
630
|
+
// Spacing Scale Detector Class
|
|
631
|
+
// ============================================================================
|
|
632
|
+
/**
|
|
633
|
+
* Detector for spacing scale adherence patterns
|
|
634
|
+
*
|
|
635
|
+
* Identifies consistent spacing patterns and flags arbitrary values
|
|
636
|
+
* that don't follow the established scale.
|
|
637
|
+
*
|
|
638
|
+
* @requirements 9.2 - THE Styling_Detector SHALL detect spacing scale adherence (p-4 vs arbitrary values)
|
|
639
|
+
*/
|
|
640
|
+
export class SpacingScaleDetector extends RegexDetector {
|
|
641
|
+
id = 'styling/spacing-scale';
|
|
642
|
+
category = 'styling';
|
|
643
|
+
subcategory = 'spacing-scale';
|
|
644
|
+
name = 'Spacing Scale Detector';
|
|
645
|
+
description = 'Detects spacing scale adherence and flags arbitrary spacing values';
|
|
646
|
+
supportedLanguages = ['typescript', 'javascript', 'css'];
|
|
647
|
+
/**
|
|
648
|
+
* Detect spacing scale patterns and violations
|
|
649
|
+
*/
|
|
650
|
+
async detect(context) {
|
|
651
|
+
const patterns = [];
|
|
652
|
+
const violations = [];
|
|
653
|
+
// Analyze the file
|
|
654
|
+
const analysis = analyzeSpacingScale(context.content, context.file);
|
|
655
|
+
// Create pattern matches for spacing patterns
|
|
656
|
+
if (analysis.usesTailwindSpacing) {
|
|
657
|
+
patterns.push(this.createTailwindSpacingPattern(context.file, analysis));
|
|
658
|
+
}
|
|
659
|
+
if (analysis.usesCSSSpacingProperties) {
|
|
660
|
+
patterns.push(this.createCSSSpacingPropertyPattern(context.file, analysis));
|
|
661
|
+
}
|
|
662
|
+
if (analysis.usesThemeSpacing) {
|
|
663
|
+
patterns.push(this.createThemeSpacingPattern(context.file, analysis));
|
|
664
|
+
}
|
|
665
|
+
// Create violations for arbitrary values
|
|
666
|
+
for (const arbitrary of analysis.arbitraryValues) {
|
|
667
|
+
violations.push(this.createArbitraryValueViolation(arbitrary));
|
|
668
|
+
}
|
|
669
|
+
return this.createResult(patterns, violations, analysis.scaleAdherenceConfidence);
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Create a pattern match for Tailwind spacing usage
|
|
673
|
+
*/
|
|
674
|
+
createTailwindSpacingPattern(file, analysis) {
|
|
675
|
+
const tailwindPatterns = analysis.spacingPatterns.filter(p => p.type === 'tailwind-spacing');
|
|
676
|
+
const firstPattern = tailwindPatterns[0];
|
|
677
|
+
return {
|
|
678
|
+
patternId: `${this.id}/tailwind`,
|
|
679
|
+
location: {
|
|
680
|
+
file,
|
|
681
|
+
line: firstPattern?.line || 1,
|
|
682
|
+
column: firstPattern?.column || 1,
|
|
683
|
+
},
|
|
684
|
+
confidence: 1.0,
|
|
685
|
+
isOutlier: false,
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Create a pattern match for CSS spacing property usage
|
|
690
|
+
*/
|
|
691
|
+
createCSSSpacingPropertyPattern(file, analysis) {
|
|
692
|
+
const cssPatterns = analysis.spacingPatterns.filter(p => p.type === 'css-spacing-property');
|
|
693
|
+
const firstPattern = cssPatterns[0];
|
|
694
|
+
return {
|
|
695
|
+
patternId: `${this.id}/css-property`,
|
|
696
|
+
location: {
|
|
697
|
+
file,
|
|
698
|
+
line: firstPattern?.line || 1,
|
|
699
|
+
column: firstPattern?.column || 1,
|
|
700
|
+
},
|
|
701
|
+
confidence: 1.0,
|
|
702
|
+
isOutlier: false,
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Create a pattern match for theme spacing usage
|
|
707
|
+
*/
|
|
708
|
+
createThemeSpacingPattern(file, analysis) {
|
|
709
|
+
const themePatterns = analysis.spacingPatterns.filter(p => p.type === 'theme-spacing');
|
|
710
|
+
const firstPattern = themePatterns[0];
|
|
711
|
+
return {
|
|
712
|
+
patternId: `${this.id}/theme`,
|
|
713
|
+
location: {
|
|
714
|
+
file,
|
|
715
|
+
line: firstPattern?.line || 1,
|
|
716
|
+
column: firstPattern?.column || 1,
|
|
717
|
+
},
|
|
718
|
+
confidence: 1.0,
|
|
719
|
+
isOutlier: false,
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Create a violation for an arbitrary spacing value
|
|
724
|
+
*/
|
|
725
|
+
createArbitraryValueViolation(arbitrary) {
|
|
726
|
+
const typeDescriptions = {
|
|
727
|
+
'arbitrary-px': 'arbitrary pixel spacing',
|
|
728
|
+
'arbitrary-rem': 'arbitrary rem spacing',
|
|
729
|
+
'arbitrary-em': 'arbitrary em spacing',
|
|
730
|
+
'tailwind-arbitrary': 'Tailwind arbitrary spacing',
|
|
731
|
+
'mixed-units': 'mixed spacing units',
|
|
732
|
+
};
|
|
733
|
+
const typeDescription = typeDescriptions[arbitrary.type] || 'arbitrary spacing';
|
|
734
|
+
const propertyInfo = arbitrary.property ? ` in '${arbitrary.property}'` : '';
|
|
735
|
+
const violation = {
|
|
736
|
+
id: `${this.id}-${arbitrary.file}-${arbitrary.line}-${arbitrary.column}`,
|
|
737
|
+
patternId: this.id,
|
|
738
|
+
severity: 'warning',
|
|
739
|
+
file: arbitrary.file,
|
|
740
|
+
range: {
|
|
741
|
+
start: { line: arbitrary.line - 1, character: arbitrary.column - 1 },
|
|
742
|
+
end: { line: arbitrary.endLine - 1, character: arbitrary.endColumn - 1 },
|
|
743
|
+
},
|
|
744
|
+
message: `${typeDescription.charAt(0).toUpperCase() + typeDescription.slice(1)} '${arbitrary.value}'${propertyInfo} doesn't follow the spacing scale`,
|
|
745
|
+
explanation: `Using arbitrary spacing values instead of scale-based values makes it difficult to maintain consistent spacing across the application. Use values from your spacing scale (4px increments, Tailwind classes, or CSS custom properties).`,
|
|
746
|
+
expected: arbitrary.suggestedValue || 'A spacing scale value',
|
|
747
|
+
actual: arbitrary.value,
|
|
748
|
+
aiExplainAvailable: true,
|
|
749
|
+
aiFixAvailable: true,
|
|
750
|
+
firstSeen: new Date(),
|
|
751
|
+
occurrences: 1,
|
|
752
|
+
};
|
|
753
|
+
const quickFix = this.createQuickFixForArbitraryValue(arbitrary);
|
|
754
|
+
if (quickFix !== undefined) {
|
|
755
|
+
violation.quickFix = quickFix;
|
|
756
|
+
}
|
|
757
|
+
return violation;
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Create a quick fix for replacing an arbitrary value with a scale value
|
|
761
|
+
*/
|
|
762
|
+
createQuickFixForArbitraryValue(arbitrary) {
|
|
763
|
+
// Only provide quick fix if we have a suggested value
|
|
764
|
+
if (!arbitrary.suggestedValue) {
|
|
765
|
+
return undefined;
|
|
766
|
+
}
|
|
767
|
+
// Extract the first suggested value (before "or")
|
|
768
|
+
const suggestedValue = arbitrary.suggestedValue.split(' or ')[0] || arbitrary.suggestedValue;
|
|
769
|
+
// Determine the replacement based on type
|
|
770
|
+
let replacement;
|
|
771
|
+
if (arbitrary.type === 'tailwind-arbitrary') {
|
|
772
|
+
// For Tailwind arbitrary values, suggest the class without brackets
|
|
773
|
+
const classMatch = arbitrary.value.match(/^([a-z-]+)-\[/);
|
|
774
|
+
const prefix = classMatch ? classMatch[1] : 'p';
|
|
775
|
+
const valueMatch = suggestedValue.match(/value (\d+)/);
|
|
776
|
+
const scaleValue = valueMatch ? valueMatch[1] : '4';
|
|
777
|
+
replacement = `${prefix}-${scaleValue}`;
|
|
778
|
+
}
|
|
779
|
+
else {
|
|
780
|
+
// For CSS values, use the suggested pixel/rem value
|
|
781
|
+
replacement = suggestedValue.match(/^[\d.]+(?:px|rem|em)/)?.[0] || suggestedValue;
|
|
782
|
+
}
|
|
783
|
+
return {
|
|
784
|
+
title: `Replace with scale value: ${replacement}`,
|
|
785
|
+
kind: 'quickfix',
|
|
786
|
+
edit: {
|
|
787
|
+
changes: {
|
|
788
|
+
[arbitrary.file]: [
|
|
789
|
+
{
|
|
790
|
+
range: {
|
|
791
|
+
start: { line: arbitrary.line - 1, character: arbitrary.column - 1 },
|
|
792
|
+
end: { line: arbitrary.endLine - 1, character: arbitrary.endColumn - 1 },
|
|
793
|
+
},
|
|
794
|
+
newText: replacement,
|
|
795
|
+
},
|
|
796
|
+
],
|
|
797
|
+
},
|
|
798
|
+
},
|
|
799
|
+
isPreferred: true,
|
|
800
|
+
confidence: 0.7,
|
|
801
|
+
preview: `Replace '${arbitrary.value}' with '${replacement}'`,
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Generate a quick fix for a violation
|
|
806
|
+
*/
|
|
807
|
+
generateQuickFix(violation) {
|
|
808
|
+
// Check if this is an arbitrary spacing violation
|
|
809
|
+
if (!violation.message.includes('spacing')) {
|
|
810
|
+
return null;
|
|
811
|
+
}
|
|
812
|
+
// Extract the value from the message
|
|
813
|
+
const valueMatch = violation.message.match(/['"]([^'"]+)['"]/);
|
|
814
|
+
if (!valueMatch || !valueMatch[1]) {
|
|
815
|
+
return null;
|
|
816
|
+
}
|
|
817
|
+
const value = valueMatch[1];
|
|
818
|
+
// Determine the type and suggest replacement
|
|
819
|
+
let suggestedValue;
|
|
820
|
+
if (value.endsWith('px')) {
|
|
821
|
+
const numValue = parseInt(value, 10);
|
|
822
|
+
suggestedValue = suggestPxSpacingValue(numValue);
|
|
823
|
+
}
|
|
824
|
+
else if (value.endsWith('rem')) {
|
|
825
|
+
const numValue = parseFloat(value);
|
|
826
|
+
suggestedValue = suggestRemSpacingValue(numValue);
|
|
827
|
+
}
|
|
828
|
+
else if (value.includes('[')) {
|
|
829
|
+
// Tailwind arbitrary value
|
|
830
|
+
suggestedValue = 'Use a standard Tailwind spacing class';
|
|
831
|
+
}
|
|
832
|
+
else {
|
|
833
|
+
return null;
|
|
834
|
+
}
|
|
835
|
+
const firstSuggestion = suggestedValue.split(' or ')[0] || suggestedValue;
|
|
836
|
+
const replacement = firstSuggestion.match(/^[\d.]+(?:px|rem|em)/)?.[0] || firstSuggestion;
|
|
837
|
+
return {
|
|
838
|
+
title: `Replace with scale value: ${replacement}`,
|
|
839
|
+
kind: 'quickfix',
|
|
840
|
+
edit: {
|
|
841
|
+
changes: {
|
|
842
|
+
[violation.file]: [
|
|
843
|
+
{
|
|
844
|
+
range: violation.range,
|
|
845
|
+
newText: replacement,
|
|
846
|
+
},
|
|
847
|
+
],
|
|
848
|
+
},
|
|
849
|
+
},
|
|
850
|
+
isPreferred: true,
|
|
851
|
+
confidence: 0.7,
|
|
852
|
+
preview: `Replace '${value}' with '${replacement}'`,
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
// ============================================================================
|
|
857
|
+
// Factory Function
|
|
858
|
+
// ============================================================================
|
|
859
|
+
/**
|
|
860
|
+
* Create a new SpacingScaleDetector instance
|
|
861
|
+
*/
|
|
862
|
+
export function createSpacingScaleDetector() {
|
|
863
|
+
return new SpacingScaleDetector();
|
|
864
|
+
}
|
|
865
|
+
//# sourceMappingURL=spacing-scale.js.map
|