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,732 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color Usage Detector - Color pattern detection
|
|
3
|
+
*
|
|
4
|
+
* Detects color usage patterns including:
|
|
5
|
+
* - CSS custom properties for colors (--color-*, var(--color-*))
|
|
6
|
+
* - Theme color objects (theme.colors.*, colors.primary, etc.)
|
|
7
|
+
* - Tailwind color classes (text-blue-500, bg-red-100, border-gray-300, etc.)
|
|
8
|
+
* - Named CSS colors (red, blue, green, etc.)
|
|
9
|
+
*
|
|
10
|
+
* Flags hardcoded color values:
|
|
11
|
+
* - Hex colors (#fff, #ffffff, #ffffffff)
|
|
12
|
+
* - RGB colors (rgb(255, 255, 255))
|
|
13
|
+
* - RGBA colors (rgba(255, 255, 255, 0.5))
|
|
14
|
+
* - HSL colors (hsl(0, 0%, 100%))
|
|
15
|
+
* - HSLA colors (hsla(0, 0%, 100%, 0.5))
|
|
16
|
+
*
|
|
17
|
+
* @requirements 9.3 - THE Styling_Detector SHALL detect color usage patterns (system colors vs hex)
|
|
18
|
+
*/
|
|
19
|
+
import { RegexDetector } from '../base/index.js';
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Constants
|
|
22
|
+
// ============================================================================
|
|
23
|
+
/**
|
|
24
|
+
* Regex pattern for CSS custom properties for colors
|
|
25
|
+
*/
|
|
26
|
+
export const CSS_COLOR_PROPERTY_PATTERN = /var\(\s*--(?:color|clr|c)[-_]?([a-zA-Z0-9_-]*)\s*(?:,\s*[^)]+)?\)/g;
|
|
27
|
+
/**
|
|
28
|
+
* Regex patterns for theme color object usage
|
|
29
|
+
*/
|
|
30
|
+
export const THEME_COLOR_PATTERNS = [
|
|
31
|
+
// theme.colors.*, theme.color.*
|
|
32
|
+
/theme\.colors?\.([a-zA-Z0-9_.[\]]+)/g,
|
|
33
|
+
// ${theme.colors.*} in template literals
|
|
34
|
+
/\$\{theme\.colors?\.([a-zA-Z0-9_.[\]]+)\}/g,
|
|
35
|
+
// props.theme.colors.*
|
|
36
|
+
/props\.theme\.colors?\.([a-zA-Z0-9_.[\]]+)/g,
|
|
37
|
+
// colors.primary, colors.secondary, etc. (standalone color object)
|
|
38
|
+
/\bcolors\.([a-zA-Z0-9_.[\]]+)/g,
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* Tailwind color class patterns
|
|
42
|
+
*/
|
|
43
|
+
export const TAILWIND_COLOR_PATTERNS = [
|
|
44
|
+
// Text colors: text-red-500, text-blue-100
|
|
45
|
+
/\btext-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
46
|
+
// Background colors: bg-red-500, bg-blue-100
|
|
47
|
+
/\bbg-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
48
|
+
// Border colors: border-red-500, border-blue-100
|
|
49
|
+
/\bborder-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
50
|
+
// Ring colors: ring-red-500, ring-blue-100
|
|
51
|
+
/\bring-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
52
|
+
// Divide colors: divide-red-500, divide-blue-100
|
|
53
|
+
/\bdivide-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
54
|
+
// Outline colors: outline-red-500, outline-blue-100
|
|
55
|
+
/\boutline-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
56
|
+
// Fill colors: fill-red-500, fill-blue-100
|
|
57
|
+
/\bfill-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
58
|
+
// Stroke colors: stroke-red-500, stroke-blue-100
|
|
59
|
+
/\bstroke-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
60
|
+
// Accent colors: accent-red-500, accent-blue-100
|
|
61
|
+
/\baccent-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
62
|
+
// Caret colors: caret-red-500, caret-blue-100
|
|
63
|
+
/\bcaret-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
64
|
+
// Shadow colors: shadow-red-500, shadow-blue-100
|
|
65
|
+
/\bshadow-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
66
|
+
// Decoration colors: decoration-red-500, decoration-blue-100
|
|
67
|
+
/\bdecoration-(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|black|white)-(?:\d{2,3}|50)\b/g,
|
|
68
|
+
];
|
|
69
|
+
/**
|
|
70
|
+
* Regex patterns for hardcoded color values
|
|
71
|
+
*/
|
|
72
|
+
export const HARDCODED_COLOR_PATTERNS = {
|
|
73
|
+
// Hex colors: #fff, #ffffff, #ffffffff (with alpha)
|
|
74
|
+
hex: /#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b/g,
|
|
75
|
+
// RGB colors: rgb(255, 255, 255)
|
|
76
|
+
rgb: /rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)/gi,
|
|
77
|
+
// RGBA colors: rgba(255, 255, 255, 0.5)
|
|
78
|
+
rgba: /rgba\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*[\d.]+\s*\)/gi,
|
|
79
|
+
// HSL colors: hsl(0, 0%, 100%)
|
|
80
|
+
hsl: /hsl\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\s*\)/gi,
|
|
81
|
+
// HSLA colors: hsla(0, 0%, 100%, 0.5)
|
|
82
|
+
hsla: /hsla\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\s*,\s*[\d.]+\s*\)/gi,
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Named CSS colors to detect
|
|
86
|
+
*/
|
|
87
|
+
export const NAMED_CSS_COLORS = [
|
|
88
|
+
'aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure',
|
|
89
|
+
'beige', 'bisque', 'blanchedalmond', 'blue', 'blueviolet',
|
|
90
|
+
'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate',
|
|
91
|
+
'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan',
|
|
92
|
+
'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen',
|
|
93
|
+
'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange',
|
|
94
|
+
'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue',
|
|
95
|
+
'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink',
|
|
96
|
+
'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick',
|
|
97
|
+
'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro', 'ghostwhite',
|
|
98
|
+
'gold', 'goldenrod', 'gray', 'green', 'greenyellow',
|
|
99
|
+
'grey', 'honeydew', 'hotpink', 'indianred', 'indigo',
|
|
100
|
+
'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen',
|
|
101
|
+
'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow',
|
|
102
|
+
'lightgray', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon',
|
|
103
|
+
'lightseagreen', 'lightskyblue', 'lightslategray', 'lightslategrey', 'lightsteelblue',
|
|
104
|
+
'lightyellow', 'lime', 'limegreen', 'linen', 'magenta',
|
|
105
|
+
'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple',
|
|
106
|
+
'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred',
|
|
107
|
+
'midnightblue', 'mintcream', 'mistyrose', 'moccasin', 'navajowhite',
|
|
108
|
+
'navy', 'oldlace', 'olive', 'olivedrab', 'orange',
|
|
109
|
+
'orangered', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise',
|
|
110
|
+
'palevioletred', 'papayawhip', 'peachpuff', 'peru', 'pink',
|
|
111
|
+
'plum', 'powderblue', 'purple', 'rebeccapurple', 'red',
|
|
112
|
+
'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown',
|
|
113
|
+
'seagreen', 'seashell', 'sienna', 'silver', 'skyblue',
|
|
114
|
+
'slateblue', 'slategray', 'slategrey', 'snow', 'springgreen',
|
|
115
|
+
'steelblue', 'tan', 'teal', 'thistle', 'tomato',
|
|
116
|
+
'turquoise', 'violet', 'wheat', 'whitesmoke', 'yellow', 'yellowgreen',
|
|
117
|
+
];
|
|
118
|
+
/**
|
|
119
|
+
* CSS properties that commonly use color values
|
|
120
|
+
*/
|
|
121
|
+
export const COLOR_PROPERTIES = [
|
|
122
|
+
'color',
|
|
123
|
+
'background-color',
|
|
124
|
+
'background',
|
|
125
|
+
'border-color',
|
|
126
|
+
'border',
|
|
127
|
+
'border-top-color',
|
|
128
|
+
'border-right-color',
|
|
129
|
+
'border-bottom-color',
|
|
130
|
+
'border-left-color',
|
|
131
|
+
'outline-color',
|
|
132
|
+
'outline',
|
|
133
|
+
'fill',
|
|
134
|
+
'stroke',
|
|
135
|
+
'box-shadow',
|
|
136
|
+
'text-shadow',
|
|
137
|
+
'text-decoration-color',
|
|
138
|
+
'caret-color',
|
|
139
|
+
'accent-color',
|
|
140
|
+
'column-rule-color',
|
|
141
|
+
];
|
|
142
|
+
/**
|
|
143
|
+
* Allowed hardcoded color values (common exceptions)
|
|
144
|
+
* Note: Values are stored in lowercase for case-insensitive comparison
|
|
145
|
+
*/
|
|
146
|
+
export const ALLOWED_HARDCODED_COLORS = new Set([
|
|
147
|
+
'transparent',
|
|
148
|
+
'currentcolor',
|
|
149
|
+
'inherit',
|
|
150
|
+
'initial',
|
|
151
|
+
'unset',
|
|
152
|
+
'#000',
|
|
153
|
+
'#000000',
|
|
154
|
+
'#fff',
|
|
155
|
+
'#ffffff',
|
|
156
|
+
'black',
|
|
157
|
+
'white',
|
|
158
|
+
]);
|
|
159
|
+
/**
|
|
160
|
+
* File patterns to exclude from hardcoded color detection
|
|
161
|
+
*/
|
|
162
|
+
export const EXCLUDED_FILE_PATTERNS = [
|
|
163
|
+
/\.test\.[jt]sx?$/,
|
|
164
|
+
/\.spec\.[jt]sx?$/,
|
|
165
|
+
/\.stories\.[jt]sx?$/,
|
|
166
|
+
/design-tokens?\//,
|
|
167
|
+
/tokens?\//,
|
|
168
|
+
/theme\//,
|
|
169
|
+
/\.config\.[jt]s$/,
|
|
170
|
+
/tailwind\.config/,
|
|
171
|
+
/colors?\.[jt]s$/,
|
|
172
|
+
/palette\.[jt]s$/,
|
|
173
|
+
];
|
|
174
|
+
// ============================================================================
|
|
175
|
+
// Helper Functions
|
|
176
|
+
// ============================================================================
|
|
177
|
+
/**
|
|
178
|
+
* Check if a file should be excluded from hardcoded color detection
|
|
179
|
+
*/
|
|
180
|
+
export function shouldExcludeFile(filePath) {
|
|
181
|
+
return EXCLUDED_FILE_PATTERNS.some(pattern => pattern.test(filePath));
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Check if a value is in the allowed hardcoded colors list
|
|
185
|
+
*/
|
|
186
|
+
export function isAllowedHardcodedColor(value) {
|
|
187
|
+
return ALLOWED_HARDCODED_COLORS.has(value.toLowerCase().trim());
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Check if a position is inside a comment
|
|
191
|
+
*/
|
|
192
|
+
function isInsideComment(content, index) {
|
|
193
|
+
const beforeIndex = content.slice(0, index);
|
|
194
|
+
// Check for single-line comment
|
|
195
|
+
const lastNewline = beforeIndex.lastIndexOf('\n');
|
|
196
|
+
const currentLine = beforeIndex.slice(lastNewline + 1);
|
|
197
|
+
if (currentLine.includes('//')) {
|
|
198
|
+
const commentStart = currentLine.indexOf('//');
|
|
199
|
+
const positionInLine = index - lastNewline - 1;
|
|
200
|
+
if (positionInLine > commentStart) {
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
// Check for multi-line comment
|
|
205
|
+
const lastBlockCommentStart = beforeIndex.lastIndexOf('/*');
|
|
206
|
+
const lastBlockCommentEnd = beforeIndex.lastIndexOf('*/');
|
|
207
|
+
if (lastBlockCommentStart > lastBlockCommentEnd) {
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Extract CSS property name from a line
|
|
214
|
+
*/
|
|
215
|
+
function extractCSSProperty(line) {
|
|
216
|
+
// Match CSS property: property-name: value
|
|
217
|
+
const cssMatch = line.match(/([a-zA-Z-]+)\s*:/);
|
|
218
|
+
if (cssMatch && cssMatch[1]) {
|
|
219
|
+
return cssMatch[1];
|
|
220
|
+
}
|
|
221
|
+
// Match JS object property: propertyName: value
|
|
222
|
+
const jsMatch = line.match(/([a-zA-Z]+)\s*:/);
|
|
223
|
+
if (jsMatch && jsMatch[1]) {
|
|
224
|
+
// Convert camelCase to kebab-case
|
|
225
|
+
return jsMatch[1].replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
226
|
+
}
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Detect CSS custom property usage for colors
|
|
231
|
+
*/
|
|
232
|
+
export function detectCSSColorProperties(content, file) {
|
|
233
|
+
const results = [];
|
|
234
|
+
const lines = content.split('\n');
|
|
235
|
+
const regex = new RegExp(CSS_COLOR_PROPERTY_PATTERN.source, CSS_COLOR_PROPERTY_PATTERN.flags);
|
|
236
|
+
let match;
|
|
237
|
+
while ((match = regex.exec(content)) !== null) {
|
|
238
|
+
const beforeMatch = content.slice(0, match.index);
|
|
239
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
240
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
241
|
+
const column = match.index - lastNewline;
|
|
242
|
+
results.push({
|
|
243
|
+
type: 'css-color-property',
|
|
244
|
+
file,
|
|
245
|
+
line: lineNumber,
|
|
246
|
+
column,
|
|
247
|
+
matchedText: match[0],
|
|
248
|
+
colorName: match[1] || '',
|
|
249
|
+
context: lines[lineNumber - 1] || '',
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
return results;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Detect theme color object usage
|
|
256
|
+
*/
|
|
257
|
+
export function detectThemeColors(content, file) {
|
|
258
|
+
const results = [];
|
|
259
|
+
const lines = content.split('\n');
|
|
260
|
+
for (const pattern of THEME_COLOR_PATTERNS) {
|
|
261
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
262
|
+
let match;
|
|
263
|
+
while ((match = regex.exec(content)) !== null) {
|
|
264
|
+
const beforeMatch = content.slice(0, match.index);
|
|
265
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
266
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
267
|
+
const column = match.index - lastNewline;
|
|
268
|
+
results.push({
|
|
269
|
+
type: 'theme-color',
|
|
270
|
+
file,
|
|
271
|
+
line: lineNumber,
|
|
272
|
+
column,
|
|
273
|
+
matchedText: match[0],
|
|
274
|
+
colorName: match[1] || match[0],
|
|
275
|
+
context: lines[lineNumber - 1] || '',
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return results;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Detect Tailwind color classes
|
|
283
|
+
*/
|
|
284
|
+
export function detectTailwindColors(content, file) {
|
|
285
|
+
const results = [];
|
|
286
|
+
const lines = content.split('\n');
|
|
287
|
+
for (const pattern of TAILWIND_COLOR_PATTERNS) {
|
|
288
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
289
|
+
let match;
|
|
290
|
+
while ((match = regex.exec(content)) !== null) {
|
|
291
|
+
const beforeMatch = content.slice(0, match.index);
|
|
292
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
293
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
294
|
+
const column = match.index - lastNewline;
|
|
295
|
+
results.push({
|
|
296
|
+
type: 'tailwind-color',
|
|
297
|
+
file,
|
|
298
|
+
line: lineNumber,
|
|
299
|
+
column,
|
|
300
|
+
matchedText: match[0],
|
|
301
|
+
colorName: match[0],
|
|
302
|
+
context: lines[lineNumber - 1] || '',
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return results;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Detect named CSS colors
|
|
310
|
+
*/
|
|
311
|
+
export function detectNamedCSSColors(content, file) {
|
|
312
|
+
const results = [];
|
|
313
|
+
const lines = content.split('\n');
|
|
314
|
+
// Create a pattern that matches named colors as whole words in CSS context
|
|
315
|
+
const colorPattern = new RegExp(`\\b(${NAMED_CSS_COLORS.join('|')})\\b(?=\\s*[;,})])`, 'gi');
|
|
316
|
+
let match;
|
|
317
|
+
while ((match = colorPattern.exec(content)) !== null) {
|
|
318
|
+
const colorName = match[1]?.toLowerCase() || '';
|
|
319
|
+
// Skip black and white as they're allowed
|
|
320
|
+
if (colorName === 'black' || colorName === 'white') {
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
// Skip if inside a comment
|
|
324
|
+
if (isInsideComment(content, match.index)) {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
const beforeMatch = content.slice(0, match.index);
|
|
328
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
329
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
330
|
+
const column = match.index - lastNewline;
|
|
331
|
+
results.push({
|
|
332
|
+
type: 'named-css-color',
|
|
333
|
+
file,
|
|
334
|
+
line: lineNumber,
|
|
335
|
+
column,
|
|
336
|
+
matchedText: match[0],
|
|
337
|
+
colorName: colorName,
|
|
338
|
+
context: lines[lineNumber - 1] || '',
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
return results;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Detect hardcoded color values
|
|
345
|
+
*/
|
|
346
|
+
export function detectHardcodedColors(content, file) {
|
|
347
|
+
const results = [];
|
|
348
|
+
const lines = content.split('\n');
|
|
349
|
+
// Check each color pattern type
|
|
350
|
+
const colorPatterns = [
|
|
351
|
+
{ pattern: HARDCODED_COLOR_PATTERNS.hex, type: 'color-hex' },
|
|
352
|
+
{ pattern: HARDCODED_COLOR_PATTERNS.rgb, type: 'color-rgb' },
|
|
353
|
+
{ pattern: HARDCODED_COLOR_PATTERNS.rgba, type: 'color-rgba' },
|
|
354
|
+
{ pattern: HARDCODED_COLOR_PATTERNS.hsl, type: 'color-hsl' },
|
|
355
|
+
{ pattern: HARDCODED_COLOR_PATTERNS.hsla, type: 'color-hsla' },
|
|
356
|
+
];
|
|
357
|
+
for (const { pattern, type } of colorPatterns) {
|
|
358
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
359
|
+
let match;
|
|
360
|
+
while ((match = regex.exec(content)) !== null) {
|
|
361
|
+
const value = match[0];
|
|
362
|
+
// Skip allowed values
|
|
363
|
+
if (isAllowedHardcodedColor(value)) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
// Skip if inside a CSS custom property definition
|
|
367
|
+
const beforeMatch = content.slice(0, match.index);
|
|
368
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
369
|
+
const lineContent = lines[lineNumber - 1] || '';
|
|
370
|
+
// Skip CSS custom property definitions (--color-name: #fff)
|
|
371
|
+
if (/^\s*--[a-zA-Z0-9_-]+\s*:/.test(lineContent)) {
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
// Skip if inside a comment
|
|
375
|
+
if (isInsideComment(content, match.index)) {
|
|
376
|
+
continue;
|
|
377
|
+
}
|
|
378
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
379
|
+
const column = match.index - lastNewline;
|
|
380
|
+
const endColumn = column + value.length;
|
|
381
|
+
const property = extractCSSProperty(lineContent);
|
|
382
|
+
const hardcodedInfo = {
|
|
383
|
+
type,
|
|
384
|
+
file,
|
|
385
|
+
line: lineNumber,
|
|
386
|
+
column,
|
|
387
|
+
endLine: lineNumber,
|
|
388
|
+
endColumn,
|
|
389
|
+
value,
|
|
390
|
+
suggestedToken: suggestColorToken(value),
|
|
391
|
+
lineContent,
|
|
392
|
+
};
|
|
393
|
+
if (property !== undefined) {
|
|
394
|
+
hardcodedInfo.property = property;
|
|
395
|
+
}
|
|
396
|
+
results.push(hardcodedInfo);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return results;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Suggest a color token for a hardcoded color value
|
|
403
|
+
*/
|
|
404
|
+
export function suggestColorToken(value) {
|
|
405
|
+
// Normalize the value
|
|
406
|
+
const normalized = value.toLowerCase();
|
|
407
|
+
// Common color mappings based on hex values
|
|
408
|
+
if (normalized === '#000' || normalized === '#000000') {
|
|
409
|
+
return 'colors.black or --color-black';
|
|
410
|
+
}
|
|
411
|
+
if (normalized === '#fff' || normalized === '#ffffff') {
|
|
412
|
+
return 'colors.white or --color-white';
|
|
413
|
+
}
|
|
414
|
+
// Try to identify color family from hex
|
|
415
|
+
if (normalized.startsWith('#')) {
|
|
416
|
+
const colorFamily = identifyColorFamily(normalized);
|
|
417
|
+
if (colorFamily) {
|
|
418
|
+
return `colors.${colorFamily} or --color-${colorFamily}`;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
// Generic suggestion
|
|
422
|
+
return 'Use a design token from your color palette (e.g., colors.primary, --color-primary)';
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Identify color family from hex value
|
|
426
|
+
*/
|
|
427
|
+
function identifyColorFamily(hex) {
|
|
428
|
+
// Normalize to 6-digit hex
|
|
429
|
+
let normalizedHex = hex.toLowerCase().replace('#', '');
|
|
430
|
+
if (normalizedHex.length === 3) {
|
|
431
|
+
normalizedHex = normalizedHex.split('').map(c => c + c).join('');
|
|
432
|
+
}
|
|
433
|
+
if (normalizedHex.length === 8) {
|
|
434
|
+
normalizedHex = normalizedHex.slice(0, 6);
|
|
435
|
+
}
|
|
436
|
+
const r = parseInt(normalizedHex.slice(0, 2), 16);
|
|
437
|
+
const g = parseInt(normalizedHex.slice(2, 4), 16);
|
|
438
|
+
const b = parseInt(normalizedHex.slice(4, 6), 16);
|
|
439
|
+
// Simple heuristics for color family identification
|
|
440
|
+
if (r > 200 && g < 100 && b < 100)
|
|
441
|
+
return 'red';
|
|
442
|
+
if (r < 100 && g > 200 && b < 100)
|
|
443
|
+
return 'green';
|
|
444
|
+
if (r < 100 && g < 100 && b > 200)
|
|
445
|
+
return 'blue';
|
|
446
|
+
if (r > 200 && g > 200 && b < 100)
|
|
447
|
+
return 'yellow';
|
|
448
|
+
if (r > 200 && g < 150 && b > 200)
|
|
449
|
+
return 'pink';
|
|
450
|
+
if (r > 200 && g > 100 && b < 100)
|
|
451
|
+
return 'orange';
|
|
452
|
+
if (r > 100 && g < 100 && b > 200)
|
|
453
|
+
return 'purple';
|
|
454
|
+
if (r < 100 && g > 200 && b > 200)
|
|
455
|
+
return 'cyan';
|
|
456
|
+
if (Math.abs(r - g) < 30 && Math.abs(g - b) < 30 && Math.abs(r - b) < 30) {
|
|
457
|
+
if (r < 50)
|
|
458
|
+
return 'black';
|
|
459
|
+
if (r > 200)
|
|
460
|
+
return 'white';
|
|
461
|
+
return 'gray';
|
|
462
|
+
}
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Analyze color usage patterns in a file
|
|
467
|
+
*/
|
|
468
|
+
export function analyzeColorUsage(content, file) {
|
|
469
|
+
// Skip excluded files for hardcoded color detection
|
|
470
|
+
const skipHardcodedDetection = shouldExcludeFile(file);
|
|
471
|
+
// Detect color patterns
|
|
472
|
+
const cssColorProperties = detectCSSColorProperties(content, file);
|
|
473
|
+
const themeColors = detectThemeColors(content, file);
|
|
474
|
+
const tailwindColors = detectTailwindColors(content, file);
|
|
475
|
+
const namedCSSColors = detectNamedCSSColors(content, file);
|
|
476
|
+
const colorPatterns = [
|
|
477
|
+
...cssColorProperties,
|
|
478
|
+
...themeColors,
|
|
479
|
+
...tailwindColors,
|
|
480
|
+
...namedCSSColors,
|
|
481
|
+
];
|
|
482
|
+
// Detect hardcoded colors (unless file is excluded)
|
|
483
|
+
let hardcodedColors = [];
|
|
484
|
+
if (!skipHardcodedDetection) {
|
|
485
|
+
hardcodedColors = detectHardcodedColors(content, file);
|
|
486
|
+
}
|
|
487
|
+
// Calculate confidence
|
|
488
|
+
const hasColorPatterns = colorPatterns.length > 0;
|
|
489
|
+
const hasHardcodedColors = hardcodedColors.length > 0;
|
|
490
|
+
let colorTokenConfidence = 0;
|
|
491
|
+
if (hasColorPatterns && !hasHardcodedColors) {
|
|
492
|
+
colorTokenConfidence = 1.0;
|
|
493
|
+
}
|
|
494
|
+
else if (hasColorPatterns && hasHardcodedColors) {
|
|
495
|
+
const ratio = colorPatterns.length / (colorPatterns.length + hardcodedColors.length);
|
|
496
|
+
colorTokenConfidence = ratio;
|
|
497
|
+
}
|
|
498
|
+
else if (!hasColorPatterns && hasHardcodedColors) {
|
|
499
|
+
colorTokenConfidence = 0;
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
colorTokenConfidence = 0.5; // No color styling detected
|
|
503
|
+
}
|
|
504
|
+
return {
|
|
505
|
+
colorPatterns,
|
|
506
|
+
hardcodedColors,
|
|
507
|
+
usesCSSColorProperties: cssColorProperties.length > 0,
|
|
508
|
+
usesThemeColors: themeColors.length > 0,
|
|
509
|
+
usesTailwindColors: tailwindColors.length > 0,
|
|
510
|
+
colorTokenConfidence,
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
// ============================================================================
|
|
514
|
+
// Color Usage Detector Class
|
|
515
|
+
// ============================================================================
|
|
516
|
+
/**
|
|
517
|
+
* Detector for color usage patterns
|
|
518
|
+
*
|
|
519
|
+
* Identifies color token usage and flags hardcoded color values that should
|
|
520
|
+
* use design tokens instead.
|
|
521
|
+
*
|
|
522
|
+
* @requirements 9.3 - THE Styling_Detector SHALL detect color usage patterns (system colors vs hex)
|
|
523
|
+
*/
|
|
524
|
+
export class ColorUsageDetector extends RegexDetector {
|
|
525
|
+
id = 'styling/color-usage';
|
|
526
|
+
category = 'styling';
|
|
527
|
+
subcategory = 'color-usage';
|
|
528
|
+
name = 'Color Usage Detector';
|
|
529
|
+
description = 'Detects color usage patterns and flags hardcoded color values that should use design tokens';
|
|
530
|
+
supportedLanguages = ['typescript', 'javascript', 'css'];
|
|
531
|
+
/**
|
|
532
|
+
* Detect color patterns and violations
|
|
533
|
+
*/
|
|
534
|
+
async detect(context) {
|
|
535
|
+
const patterns = [];
|
|
536
|
+
const violations = [];
|
|
537
|
+
// Analyze the file
|
|
538
|
+
const analysis = analyzeColorUsage(context.content, context.file);
|
|
539
|
+
// Create pattern matches for color usages
|
|
540
|
+
if (analysis.usesCSSColorProperties) {
|
|
541
|
+
patterns.push(this.createCSSColorPropertyPattern(context.file, analysis));
|
|
542
|
+
}
|
|
543
|
+
if (analysis.usesThemeColors) {
|
|
544
|
+
patterns.push(this.createThemeColorPattern(context.file, analysis));
|
|
545
|
+
}
|
|
546
|
+
if (analysis.usesTailwindColors) {
|
|
547
|
+
patterns.push(this.createTailwindColorPattern(context.file, analysis));
|
|
548
|
+
}
|
|
549
|
+
// Create violations for hardcoded colors
|
|
550
|
+
for (const hardcoded of analysis.hardcodedColors) {
|
|
551
|
+
violations.push(this.createHardcodedColorViolation(hardcoded));
|
|
552
|
+
}
|
|
553
|
+
return this.createResult(patterns, violations, analysis.colorTokenConfidence);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Create a pattern match for CSS color property usage
|
|
557
|
+
*/
|
|
558
|
+
createCSSColorPropertyPattern(file, analysis) {
|
|
559
|
+
const cssPatterns = analysis.colorPatterns.filter(p => p.type === 'css-color-property');
|
|
560
|
+
const firstPattern = cssPatterns[0];
|
|
561
|
+
return {
|
|
562
|
+
patternId: `${this.id}/css-color-property`,
|
|
563
|
+
location: {
|
|
564
|
+
file,
|
|
565
|
+
line: firstPattern?.line || 1,
|
|
566
|
+
column: firstPattern?.column || 1,
|
|
567
|
+
},
|
|
568
|
+
confidence: 1.0,
|
|
569
|
+
isOutlier: false,
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Create a pattern match for theme color usage
|
|
574
|
+
*/
|
|
575
|
+
createThemeColorPattern(file, analysis) {
|
|
576
|
+
const themePatterns = analysis.colorPatterns.filter(p => p.type === 'theme-color');
|
|
577
|
+
const firstPattern = themePatterns[0];
|
|
578
|
+
return {
|
|
579
|
+
patternId: `${this.id}/theme-color`,
|
|
580
|
+
location: {
|
|
581
|
+
file,
|
|
582
|
+
line: firstPattern?.line || 1,
|
|
583
|
+
column: firstPattern?.column || 1,
|
|
584
|
+
},
|
|
585
|
+
confidence: 1.0,
|
|
586
|
+
isOutlier: false,
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Create a pattern match for Tailwind color usage
|
|
591
|
+
*/
|
|
592
|
+
createTailwindColorPattern(file, analysis) {
|
|
593
|
+
const tailwindPatterns = analysis.colorPatterns.filter(p => p.type === 'tailwind-color');
|
|
594
|
+
const firstPattern = tailwindPatterns[0];
|
|
595
|
+
return {
|
|
596
|
+
patternId: `${this.id}/tailwind-color`,
|
|
597
|
+
location: {
|
|
598
|
+
file,
|
|
599
|
+
line: firstPattern?.line || 1,
|
|
600
|
+
column: firstPattern?.column || 1,
|
|
601
|
+
},
|
|
602
|
+
confidence: 1.0,
|
|
603
|
+
isOutlier: false,
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Create a violation for a hardcoded color value
|
|
608
|
+
*/
|
|
609
|
+
createHardcodedColorViolation(hardcoded) {
|
|
610
|
+
const typeDescriptions = {
|
|
611
|
+
'color-hex': 'hex color',
|
|
612
|
+
'color-rgb': 'RGB color',
|
|
613
|
+
'color-rgba': 'RGBA color',
|
|
614
|
+
'color-hsl': 'HSL color',
|
|
615
|
+
'color-hsla': 'HSLA color',
|
|
616
|
+
};
|
|
617
|
+
const typeDescription = typeDescriptions[hardcoded.type] || 'hardcoded color';
|
|
618
|
+
const propertyInfo = hardcoded.property ? ` in '${hardcoded.property}'` : '';
|
|
619
|
+
const violation = {
|
|
620
|
+
id: `${this.id}-${hardcoded.file}-${hardcoded.line}-${hardcoded.column}`,
|
|
621
|
+
patternId: this.id,
|
|
622
|
+
severity: 'warning',
|
|
623
|
+
file: hardcoded.file,
|
|
624
|
+
range: {
|
|
625
|
+
start: { line: hardcoded.line - 1, character: hardcoded.column - 1 },
|
|
626
|
+
end: { line: hardcoded.endLine - 1, character: hardcoded.endColumn - 1 },
|
|
627
|
+
},
|
|
628
|
+
message: `Hardcoded ${typeDescription} '${hardcoded.value}'${propertyInfo} should use a color token`,
|
|
629
|
+
explanation: `Using hardcoded color values instead of design tokens makes it difficult to maintain consistent colors across the application. Color tokens provide a single source of truth for your color palette.`,
|
|
630
|
+
expected: hardcoded.suggestedToken || 'A color token',
|
|
631
|
+
actual: hardcoded.value,
|
|
632
|
+
aiExplainAvailable: true,
|
|
633
|
+
aiFixAvailable: true,
|
|
634
|
+
firstSeen: new Date(),
|
|
635
|
+
occurrences: 1,
|
|
636
|
+
};
|
|
637
|
+
const quickFix = this.createQuickFixForHardcodedColor(hardcoded);
|
|
638
|
+
if (quickFix !== undefined) {
|
|
639
|
+
violation.quickFix = quickFix;
|
|
640
|
+
}
|
|
641
|
+
return violation;
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Create a quick fix for replacing a hardcoded color with a token
|
|
645
|
+
*/
|
|
646
|
+
createQuickFixForHardcodedColor(hardcoded) {
|
|
647
|
+
// Only provide quick fix if we have a suggested token
|
|
648
|
+
if (!hardcoded.suggestedToken) {
|
|
649
|
+
return undefined;
|
|
650
|
+
}
|
|
651
|
+
// Extract the first suggested token (before "or")
|
|
652
|
+
const suggestedToken = hardcoded.suggestedToken.split(' or ')[0] || hardcoded.suggestedToken;
|
|
653
|
+
// Determine the replacement based on context
|
|
654
|
+
let replacement;
|
|
655
|
+
if (hardcoded.lineContent.includes('var(')) {
|
|
656
|
+
// Already using CSS custom properties, suggest a different custom property
|
|
657
|
+
replacement = `var(--${suggestedToken.replace(/\./g, '-').replace('colors', 'color')})`;
|
|
658
|
+
}
|
|
659
|
+
else if (hardcoded.lineContent.includes('${') || hardcoded.lineContent.includes('`')) {
|
|
660
|
+
// Template literal context (styled-components, emotion)
|
|
661
|
+
replacement = `\${${suggestedToken}}`;
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
// Default: suggest the token directly
|
|
665
|
+
replacement = suggestedToken;
|
|
666
|
+
}
|
|
667
|
+
return {
|
|
668
|
+
title: `Replace with color token: ${suggestedToken}`,
|
|
669
|
+
kind: 'quickfix',
|
|
670
|
+
edit: {
|
|
671
|
+
changes: {
|
|
672
|
+
[hardcoded.file]: [
|
|
673
|
+
{
|
|
674
|
+
range: {
|
|
675
|
+
start: { line: hardcoded.line - 1, character: hardcoded.column - 1 },
|
|
676
|
+
end: { line: hardcoded.endLine - 1, character: hardcoded.endColumn - 1 },
|
|
677
|
+
},
|
|
678
|
+
newText: replacement,
|
|
679
|
+
},
|
|
680
|
+
],
|
|
681
|
+
},
|
|
682
|
+
},
|
|
683
|
+
isPreferred: true,
|
|
684
|
+
confidence: 0.7,
|
|
685
|
+
preview: `Replace '${hardcoded.value}' with '${replacement}'`,
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Generate a quick fix for a violation
|
|
690
|
+
*/
|
|
691
|
+
generateQuickFix(violation) {
|
|
692
|
+
// Check if this is a hardcoded color violation
|
|
693
|
+
if (!violation.message.includes('Hardcoded') || !violation.message.includes('color')) {
|
|
694
|
+
return null;
|
|
695
|
+
}
|
|
696
|
+
// Extract the value from the message
|
|
697
|
+
const valueMatch = violation.message.match(/Hardcoded [^']+ '([^']+)'/);
|
|
698
|
+
if (!valueMatch || !valueMatch[1]) {
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
701
|
+
const value = valueMatch[1];
|
|
702
|
+
const suggestedToken = suggestColorToken(value);
|
|
703
|
+
const firstSuggestion = suggestedToken.split(' or ')[0] || suggestedToken;
|
|
704
|
+
return {
|
|
705
|
+
title: `Replace with color token: ${firstSuggestion}`,
|
|
706
|
+
kind: 'quickfix',
|
|
707
|
+
edit: {
|
|
708
|
+
changes: {
|
|
709
|
+
[violation.file]: [
|
|
710
|
+
{
|
|
711
|
+
range: violation.range,
|
|
712
|
+
newText: firstSuggestion,
|
|
713
|
+
},
|
|
714
|
+
],
|
|
715
|
+
},
|
|
716
|
+
},
|
|
717
|
+
isPreferred: true,
|
|
718
|
+
confidence: 0.7,
|
|
719
|
+
preview: `Replace '${value}' with '${firstSuggestion}'`,
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
// ============================================================================
|
|
724
|
+
// Factory Function
|
|
725
|
+
// ============================================================================
|
|
726
|
+
/**
|
|
727
|
+
* Create a new ColorUsageDetector instance
|
|
728
|
+
*/
|
|
729
|
+
export function createColorUsageDetector() {
|
|
730
|
+
return new ColorUsageDetector();
|
|
731
|
+
}
|
|
732
|
+
//# sourceMappingURL=color-usage.js.map
|