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,748 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Design Tokens Detector - Token usage detection
|
|
3
|
+
*
|
|
4
|
+
* Detects design token usage patterns including:
|
|
5
|
+
* - Imports from design-tokens/ directory
|
|
6
|
+
* - CSS custom properties (--token-name)
|
|
7
|
+
* - Theme object usage (theme.colors, theme.spacing, etc.)
|
|
8
|
+
* - Token variable usage in styled-components, emotion, etc.
|
|
9
|
+
*
|
|
10
|
+
* Flags hardcoded values that should use design tokens:
|
|
11
|
+
* - Hardcoded colors (hex, rgb, hsl)
|
|
12
|
+
* - Hardcoded spacing values (px, rem, em)
|
|
13
|
+
* - Hardcoded font sizes
|
|
14
|
+
* - Hardcoded border radius
|
|
15
|
+
*
|
|
16
|
+
* @requirements 9.1 - THE Styling_Detector SHALL detect design token usage vs hardcoded values
|
|
17
|
+
*/
|
|
18
|
+
import { RegexDetector } from '../base/index.js';
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Constants
|
|
21
|
+
// ============================================================================
|
|
22
|
+
/**
|
|
23
|
+
* Regex patterns for detecting design token imports
|
|
24
|
+
*/
|
|
25
|
+
export const DESIGN_TOKEN_IMPORT_PATTERNS = [
|
|
26
|
+
// Import from design-tokens directory
|
|
27
|
+
/import\s+(?:\{[^}]+\}|\*\s+as\s+\w+|\w+)\s+from\s+['"](?:@\/|\.\.?\/)*design-tokens(?:\/[^'"]*)?['"]/g,
|
|
28
|
+
// Import from tokens directory
|
|
29
|
+
/import\s+(?:\{[^}]+\}|\*\s+as\s+\w+|\w+)\s+from\s+['"](?:@\/|\.\.?\/)*tokens(?:\/[^'"]*)?['"]/g,
|
|
30
|
+
// Import from theme directory
|
|
31
|
+
/import\s+(?:\{[^}]+\}|\*\s+as\s+\w+|\w+)\s+from\s+['"](?:@\/|\.\.?\/)*theme(?:\/[^'"]*)?['"]/g,
|
|
32
|
+
// Import from styles/tokens
|
|
33
|
+
/import\s+(?:\{[^}]+\}|\*\s+as\s+\w+|\w+)\s+from\s+['"](?:@\/|\.\.?\/)*styles\/tokens(?:\/[^'"]*)?['"]/g,
|
|
34
|
+
];
|
|
35
|
+
/**
|
|
36
|
+
* Regex pattern for CSS custom properties
|
|
37
|
+
*/
|
|
38
|
+
export const CSS_CUSTOM_PROPERTY_PATTERN = /var\(\s*--([a-zA-Z0-9_-]+)\s*(?:,\s*[^)]+)?\)/g;
|
|
39
|
+
/**
|
|
40
|
+
* Regex patterns for theme object usage
|
|
41
|
+
*/
|
|
42
|
+
export const THEME_OBJECT_PATTERNS = [
|
|
43
|
+
// theme.colors.*, theme.spacing.*, etc.
|
|
44
|
+
/theme\.(?:colors?|spacing|typography|fontSizes?|borderRadius|shadows?|zIndex|breakpoints?)\.[a-zA-Z0-9_.[\]]+/g,
|
|
45
|
+
// ${theme.colors.*} in template literals
|
|
46
|
+
/\$\{theme\.(?:colors?|spacing|typography|fontSizes?|borderRadius|shadows?|zIndex|breakpoints?)\.[a-zA-Z0-9_.[\]]+\}/g,
|
|
47
|
+
// props.theme.* pattern
|
|
48
|
+
/props\.theme\.(?:colors?|spacing|typography|fontSizes?|borderRadius|shadows?|zIndex|breakpoints?)\.[a-zA-Z0-9_.[\]]+/g,
|
|
49
|
+
];
|
|
50
|
+
/**
|
|
51
|
+
* Regex patterns for hardcoded color values
|
|
52
|
+
*/
|
|
53
|
+
export const HARDCODED_COLOR_PATTERNS = {
|
|
54
|
+
// Hex colors: #fff, #ffffff, #ffffffff (with alpha)
|
|
55
|
+
hex: /#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})\b/g,
|
|
56
|
+
// RGB colors: rgb(255, 255, 255)
|
|
57
|
+
rgb: /rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)/gi,
|
|
58
|
+
// RGBA colors: rgba(255, 255, 255, 0.5)
|
|
59
|
+
rgba: /rgba\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*[\d.]+\s*\)/gi,
|
|
60
|
+
// HSL colors: hsl(0, 0%, 100%)
|
|
61
|
+
hsl: /hsl\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\s*\)/gi,
|
|
62
|
+
// HSLA colors: hsla(0, 0%, 100%, 0.5)
|
|
63
|
+
hsla: /hsla\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\s*,\s*[\d.]+\s*\)/gi,
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Regex patterns for hardcoded spacing values
|
|
67
|
+
*/
|
|
68
|
+
export const HARDCODED_SPACING_PATTERNS = {
|
|
69
|
+
// Pixel values: 10px, 20px (excluding 0px and 1px which are often intentional)
|
|
70
|
+
px: /(?<![a-zA-Z0-9_-])(?:[2-9]|[1-9]\d+)px\b/g,
|
|
71
|
+
// Rem values: 1rem, 2rem (excluding common values like 0rem)
|
|
72
|
+
rem: /(?<![a-zA-Z0-9_-])(?:0?\.\d+|\d+(?:\.\d+)?)rem\b/g,
|
|
73
|
+
// Em values: 1em, 2em
|
|
74
|
+
em: /(?<![a-zA-Z0-9_-])(?:0?\.\d+|\d+(?:\.\d+)?)em\b/g,
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* CSS properties that commonly use design tokens
|
|
78
|
+
*/
|
|
79
|
+
export const TOKEN_PROPERTIES = [
|
|
80
|
+
// Color properties
|
|
81
|
+
'color',
|
|
82
|
+
'background-color',
|
|
83
|
+
'background',
|
|
84
|
+
'border-color',
|
|
85
|
+
'border',
|
|
86
|
+
'outline-color',
|
|
87
|
+
'fill',
|
|
88
|
+
'stroke',
|
|
89
|
+
'box-shadow',
|
|
90
|
+
'text-shadow',
|
|
91
|
+
// Spacing properties
|
|
92
|
+
'margin',
|
|
93
|
+
'margin-top',
|
|
94
|
+
'margin-right',
|
|
95
|
+
'margin-bottom',
|
|
96
|
+
'margin-left',
|
|
97
|
+
'padding',
|
|
98
|
+
'padding-top',
|
|
99
|
+
'padding-right',
|
|
100
|
+
'padding-bottom',
|
|
101
|
+
'padding-left',
|
|
102
|
+
'gap',
|
|
103
|
+
'row-gap',
|
|
104
|
+
'column-gap',
|
|
105
|
+
// Typography properties
|
|
106
|
+
'font-size',
|
|
107
|
+
'line-height',
|
|
108
|
+
'letter-spacing',
|
|
109
|
+
// Border properties
|
|
110
|
+
'border-radius',
|
|
111
|
+
'border-width',
|
|
112
|
+
// Z-index
|
|
113
|
+
'z-index',
|
|
114
|
+
];
|
|
115
|
+
/**
|
|
116
|
+
* Allowed hardcoded values (common exceptions)
|
|
117
|
+
* Note: Values are stored in lowercase for case-insensitive comparison
|
|
118
|
+
*/
|
|
119
|
+
export const ALLOWED_HARDCODED_VALUES = new Set([
|
|
120
|
+
'0',
|
|
121
|
+
'0px',
|
|
122
|
+
'1px',
|
|
123
|
+
'100%',
|
|
124
|
+
'inherit',
|
|
125
|
+
'initial',
|
|
126
|
+
'unset',
|
|
127
|
+
'auto',
|
|
128
|
+
'none',
|
|
129
|
+
'transparent',
|
|
130
|
+
'currentcolor', // lowercase for case-insensitive comparison
|
|
131
|
+
'#000',
|
|
132
|
+
'#000000',
|
|
133
|
+
'#fff',
|
|
134
|
+
'#ffffff',
|
|
135
|
+
'black',
|
|
136
|
+
'white',
|
|
137
|
+
]);
|
|
138
|
+
/**
|
|
139
|
+
* File patterns to exclude from hardcoded value detection
|
|
140
|
+
*/
|
|
141
|
+
export const EXCLUDED_FILE_PATTERNS = [
|
|
142
|
+
/\.test\.[jt]sx?$/,
|
|
143
|
+
/\.spec\.[jt]sx?$/,
|
|
144
|
+
/\.stories\.[jt]sx?$/,
|
|
145
|
+
/design-tokens?\//,
|
|
146
|
+
/tokens?\//,
|
|
147
|
+
/theme\//,
|
|
148
|
+
/\.config\.[jt]s$/,
|
|
149
|
+
/tailwind\.config/,
|
|
150
|
+
];
|
|
151
|
+
// ============================================================================
|
|
152
|
+
// Helper Functions
|
|
153
|
+
// ============================================================================
|
|
154
|
+
/**
|
|
155
|
+
* Check if a file should be excluded from hardcoded value detection
|
|
156
|
+
*/
|
|
157
|
+
export function shouldExcludeFile(filePath) {
|
|
158
|
+
return EXCLUDED_FILE_PATTERNS.some(pattern => pattern.test(filePath));
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Check if a value is in the allowed hardcoded values list
|
|
162
|
+
*/
|
|
163
|
+
export function isAllowedHardcodedValue(value) {
|
|
164
|
+
return ALLOWED_HARDCODED_VALUES.has(value.toLowerCase().trim());
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Detect design token imports in content
|
|
168
|
+
*/
|
|
169
|
+
export function detectTokenImports(content, file) {
|
|
170
|
+
const results = [];
|
|
171
|
+
const lines = content.split('\n');
|
|
172
|
+
for (const pattern of DESIGN_TOKEN_IMPORT_PATTERNS) {
|
|
173
|
+
// Reset regex lastIndex
|
|
174
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
175
|
+
let match;
|
|
176
|
+
while ((match = regex.exec(content)) !== null) {
|
|
177
|
+
const beforeMatch = content.slice(0, match.index);
|
|
178
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
179
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
180
|
+
const column = match.index - lastNewline;
|
|
181
|
+
results.push({
|
|
182
|
+
type: 'design-tokens-import',
|
|
183
|
+
file,
|
|
184
|
+
line: lineNumber,
|
|
185
|
+
column,
|
|
186
|
+
matchedText: match[0],
|
|
187
|
+
tokenName: extractImportPath(match[0]),
|
|
188
|
+
context: lines[lineNumber - 1] || '',
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return results;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Extract import path from import statement
|
|
196
|
+
*/
|
|
197
|
+
function extractImportPath(importStatement) {
|
|
198
|
+
const match = importStatement.match(/from\s+['"]([^'"]+)['"]/);
|
|
199
|
+
return match ? match[1] || '' : '';
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Detect CSS custom property usage in content
|
|
203
|
+
*/
|
|
204
|
+
export function detectCSSCustomProperties(content, file) {
|
|
205
|
+
const results = [];
|
|
206
|
+
const lines = content.split('\n');
|
|
207
|
+
const regex = new RegExp(CSS_CUSTOM_PROPERTY_PATTERN.source, CSS_CUSTOM_PROPERTY_PATTERN.flags);
|
|
208
|
+
let match;
|
|
209
|
+
while ((match = regex.exec(content)) !== null) {
|
|
210
|
+
const beforeMatch = content.slice(0, match.index);
|
|
211
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
212
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
213
|
+
const column = match.index - lastNewline;
|
|
214
|
+
results.push({
|
|
215
|
+
type: 'css-custom-property',
|
|
216
|
+
file,
|
|
217
|
+
line: lineNumber,
|
|
218
|
+
column,
|
|
219
|
+
matchedText: match[0],
|
|
220
|
+
tokenName: match[1] || '',
|
|
221
|
+
context: lines[lineNumber - 1] || '',
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
return results;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Detect theme object usage in content
|
|
228
|
+
*/
|
|
229
|
+
export function detectThemeObjectUsage(content, file) {
|
|
230
|
+
const results = [];
|
|
231
|
+
const lines = content.split('\n');
|
|
232
|
+
for (const pattern of THEME_OBJECT_PATTERNS) {
|
|
233
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
234
|
+
let match;
|
|
235
|
+
while ((match = regex.exec(content)) !== null) {
|
|
236
|
+
const beforeMatch = content.slice(0, match.index);
|
|
237
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
238
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
239
|
+
const column = match.index - lastNewline;
|
|
240
|
+
results.push({
|
|
241
|
+
type: 'theme-object',
|
|
242
|
+
file,
|
|
243
|
+
line: lineNumber,
|
|
244
|
+
column,
|
|
245
|
+
matchedText: match[0],
|
|
246
|
+
tokenName: match[0],
|
|
247
|
+
context: lines[lineNumber - 1] || '',
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return results;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Detect hardcoded color values in content
|
|
255
|
+
*/
|
|
256
|
+
export function detectHardcodedColors(content, file) {
|
|
257
|
+
const results = [];
|
|
258
|
+
const lines = content.split('\n');
|
|
259
|
+
// Check each color pattern type
|
|
260
|
+
const colorPatterns = [
|
|
261
|
+
{ pattern: HARDCODED_COLOR_PATTERNS.hex, type: 'color-hex' },
|
|
262
|
+
{ pattern: HARDCODED_COLOR_PATTERNS.rgb, type: 'color-rgb' },
|
|
263
|
+
{ pattern: HARDCODED_COLOR_PATTERNS.rgba, type: 'color-rgba' },
|
|
264
|
+
{ pattern: HARDCODED_COLOR_PATTERNS.hsl, type: 'color-hsl' },
|
|
265
|
+
{ pattern: HARDCODED_COLOR_PATTERNS.hsla, type: 'color-hsla' },
|
|
266
|
+
];
|
|
267
|
+
for (const { pattern, type } of colorPatterns) {
|
|
268
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
269
|
+
let match;
|
|
270
|
+
while ((match = regex.exec(content)) !== null) {
|
|
271
|
+
const value = match[0];
|
|
272
|
+
// Skip allowed values
|
|
273
|
+
if (isAllowedHardcodedValue(value)) {
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
// Skip if inside a CSS custom property definition
|
|
277
|
+
const beforeMatch = content.slice(0, match.index);
|
|
278
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
279
|
+
const lineContent = lines[lineNumber - 1] || '';
|
|
280
|
+
// Skip CSS custom property definitions (--color-name: #fff)
|
|
281
|
+
if (/^\s*--[a-zA-Z0-9_-]+\s*:/.test(lineContent)) {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
// Skip if inside a comment
|
|
285
|
+
if (isInsideComment(content, match.index)) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
289
|
+
const column = match.index - lastNewline;
|
|
290
|
+
const endColumn = column + value.length;
|
|
291
|
+
const property = extractCSSProperty(lineContent);
|
|
292
|
+
const hardcodedInfo = {
|
|
293
|
+
type,
|
|
294
|
+
file,
|
|
295
|
+
line: lineNumber,
|
|
296
|
+
column,
|
|
297
|
+
endLine: lineNumber,
|
|
298
|
+
endColumn,
|
|
299
|
+
value,
|
|
300
|
+
suggestedToken: suggestColorToken(value),
|
|
301
|
+
lineContent,
|
|
302
|
+
};
|
|
303
|
+
if (property !== undefined) {
|
|
304
|
+
hardcodedInfo.property = property;
|
|
305
|
+
}
|
|
306
|
+
results.push(hardcodedInfo);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return results;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Detect hardcoded spacing values in content
|
|
313
|
+
*/
|
|
314
|
+
export function detectHardcodedSpacing(content, file) {
|
|
315
|
+
const results = [];
|
|
316
|
+
const lines = content.split('\n');
|
|
317
|
+
const spacingPatterns = [
|
|
318
|
+
{ pattern: HARDCODED_SPACING_PATTERNS.px, type: 'spacing-px' },
|
|
319
|
+
{ pattern: HARDCODED_SPACING_PATTERNS.rem, type: 'spacing-rem' },
|
|
320
|
+
{ pattern: HARDCODED_SPACING_PATTERNS.em, type: 'spacing-em' },
|
|
321
|
+
];
|
|
322
|
+
for (const { pattern, type } of spacingPatterns) {
|
|
323
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
324
|
+
let match;
|
|
325
|
+
while ((match = regex.exec(content)) !== null) {
|
|
326
|
+
const value = match[0];
|
|
327
|
+
// Skip allowed values
|
|
328
|
+
if (isAllowedHardcodedValue(value)) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
const beforeMatch = content.slice(0, match.index);
|
|
332
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
333
|
+
const lineContent = lines[lineNumber - 1] || '';
|
|
334
|
+
// Skip CSS custom property definitions
|
|
335
|
+
if (/^\s*--[a-zA-Z0-9_-]+\s*:/.test(lineContent)) {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
// Skip if inside a comment
|
|
339
|
+
if (isInsideComment(content, match.index)) {
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
// Skip if it's part of a media query breakpoint
|
|
343
|
+
if (/@media.*\(.*\d+px/.test(lineContent)) {
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
347
|
+
const column = match.index - lastNewline;
|
|
348
|
+
const endColumn = column + value.length;
|
|
349
|
+
const property = extractCSSProperty(lineContent);
|
|
350
|
+
const hardcodedInfo = {
|
|
351
|
+
type,
|
|
352
|
+
file,
|
|
353
|
+
line: lineNumber,
|
|
354
|
+
column,
|
|
355
|
+
endLine: lineNumber,
|
|
356
|
+
endColumn,
|
|
357
|
+
value,
|
|
358
|
+
suggestedToken: suggestSpacingToken(value),
|
|
359
|
+
lineContent,
|
|
360
|
+
};
|
|
361
|
+
if (property !== undefined) {
|
|
362
|
+
hardcodedInfo.property = property;
|
|
363
|
+
}
|
|
364
|
+
results.push(hardcodedInfo);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return results;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Check if a position is inside a comment
|
|
371
|
+
*/
|
|
372
|
+
function isInsideComment(content, index) {
|
|
373
|
+
const beforeIndex = content.slice(0, index);
|
|
374
|
+
// Check for single-line comment
|
|
375
|
+
const lastNewline = beforeIndex.lastIndexOf('\n');
|
|
376
|
+
const currentLine = beforeIndex.slice(lastNewline + 1);
|
|
377
|
+
if (currentLine.includes('//')) {
|
|
378
|
+
const commentStart = currentLine.indexOf('//');
|
|
379
|
+
const positionInLine = index - lastNewline - 1;
|
|
380
|
+
if (positionInLine > commentStart) {
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
// Check for multi-line comment
|
|
385
|
+
const lastBlockCommentStart = beforeIndex.lastIndexOf('/*');
|
|
386
|
+
const lastBlockCommentEnd = beforeIndex.lastIndexOf('*/');
|
|
387
|
+
if (lastBlockCommentStart > lastBlockCommentEnd) {
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Extract CSS property name from a line
|
|
394
|
+
*/
|
|
395
|
+
function extractCSSProperty(line) {
|
|
396
|
+
// Match CSS property: property-name: value
|
|
397
|
+
const cssMatch = line.match(/([a-zA-Z-]+)\s*:/);
|
|
398
|
+
if (cssMatch && cssMatch[1]) {
|
|
399
|
+
return cssMatch[1];
|
|
400
|
+
}
|
|
401
|
+
// Match JS object property: propertyName: value
|
|
402
|
+
const jsMatch = line.match(/([a-zA-Z]+)\s*:/);
|
|
403
|
+
if (jsMatch && jsMatch[1]) {
|
|
404
|
+
// Convert camelCase to kebab-case
|
|
405
|
+
return jsMatch[1].replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
406
|
+
}
|
|
407
|
+
return undefined;
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Suggest a token name for a color value
|
|
411
|
+
*/
|
|
412
|
+
function suggestColorToken(value) {
|
|
413
|
+
// Normalize the value
|
|
414
|
+
const normalized = value.toLowerCase();
|
|
415
|
+
// Common color mappings
|
|
416
|
+
if (normalized === '#000' || normalized === '#000000') {
|
|
417
|
+
return 'colors.black or --color-black';
|
|
418
|
+
}
|
|
419
|
+
if (normalized === '#fff' || normalized === '#ffffff') {
|
|
420
|
+
return 'colors.white or --color-white';
|
|
421
|
+
}
|
|
422
|
+
// Generic suggestion
|
|
423
|
+
return 'Use a design token from your color palette (e.g., colors.primary, --color-primary)';
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Suggest a token name for a spacing value
|
|
427
|
+
*/
|
|
428
|
+
function suggestSpacingToken(value) {
|
|
429
|
+
// Extract numeric value
|
|
430
|
+
const numMatch = value.match(/^(\d+(?:\.\d+)?)/);
|
|
431
|
+
if (!numMatch) {
|
|
432
|
+
return 'Use a spacing token (e.g., spacing.md, --spacing-4)';
|
|
433
|
+
}
|
|
434
|
+
const num = parseFloat(numMatch[1] || '0');
|
|
435
|
+
// Common spacing scale suggestions
|
|
436
|
+
if (value.endsWith('px')) {
|
|
437
|
+
if (num <= 4)
|
|
438
|
+
return 'spacing.xs or --spacing-1';
|
|
439
|
+
if (num <= 8)
|
|
440
|
+
return 'spacing.sm or --spacing-2';
|
|
441
|
+
if (num <= 16)
|
|
442
|
+
return 'spacing.md or --spacing-4';
|
|
443
|
+
if (num <= 24)
|
|
444
|
+
return 'spacing.lg or --spacing-6';
|
|
445
|
+
if (num <= 32)
|
|
446
|
+
return 'spacing.xl or --spacing-8';
|
|
447
|
+
return 'spacing.2xl or --spacing-10';
|
|
448
|
+
}
|
|
449
|
+
if (value.endsWith('rem')) {
|
|
450
|
+
if (num <= 0.25)
|
|
451
|
+
return 'spacing.xs or --spacing-1';
|
|
452
|
+
if (num <= 0.5)
|
|
453
|
+
return 'spacing.sm or --spacing-2';
|
|
454
|
+
if (num <= 1)
|
|
455
|
+
return 'spacing.md or --spacing-4';
|
|
456
|
+
if (num <= 1.5)
|
|
457
|
+
return 'spacing.lg or --spacing-6';
|
|
458
|
+
if (num <= 2)
|
|
459
|
+
return 'spacing.xl or --spacing-8';
|
|
460
|
+
return 'spacing.2xl or --spacing-10';
|
|
461
|
+
}
|
|
462
|
+
return 'Use a spacing token (e.g., spacing.md, --spacing-4)';
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Analyze design token patterns in a file
|
|
466
|
+
*/
|
|
467
|
+
export function analyzeDesignTokens(content, file) {
|
|
468
|
+
// Skip excluded files for hardcoded value detection
|
|
469
|
+
const skipHardcodedDetection = shouldExcludeFile(file);
|
|
470
|
+
// Detect token usages
|
|
471
|
+
const tokenImports = detectTokenImports(content, file);
|
|
472
|
+
const cssCustomProperties = detectCSSCustomProperties(content, file);
|
|
473
|
+
const themeObjectUsages = detectThemeObjectUsage(content, file);
|
|
474
|
+
const tokenUsages = [
|
|
475
|
+
...tokenImports,
|
|
476
|
+
...cssCustomProperties,
|
|
477
|
+
...themeObjectUsages,
|
|
478
|
+
];
|
|
479
|
+
// Detect hardcoded values (unless file is excluded)
|
|
480
|
+
let hardcodedValues = [];
|
|
481
|
+
if (!skipHardcodedDetection) {
|
|
482
|
+
const hardcodedColors = detectHardcodedColors(content, file);
|
|
483
|
+
const hardcodedSpacing = detectHardcodedSpacing(content, file);
|
|
484
|
+
hardcodedValues = [...hardcodedColors, ...hardcodedSpacing];
|
|
485
|
+
}
|
|
486
|
+
// Calculate confidence
|
|
487
|
+
const hasTokenUsage = tokenUsages.length > 0;
|
|
488
|
+
const hasHardcodedValues = hardcodedValues.length > 0;
|
|
489
|
+
let tokenUsageConfidence = 0;
|
|
490
|
+
if (hasTokenUsage && !hasHardcodedValues) {
|
|
491
|
+
tokenUsageConfidence = 1.0;
|
|
492
|
+
}
|
|
493
|
+
else if (hasTokenUsage && hasHardcodedValues) {
|
|
494
|
+
const ratio = tokenUsages.length / (tokenUsages.length + hardcodedValues.length);
|
|
495
|
+
tokenUsageConfidence = ratio;
|
|
496
|
+
}
|
|
497
|
+
else if (!hasTokenUsage && hasHardcodedValues) {
|
|
498
|
+
tokenUsageConfidence = 0;
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
tokenUsageConfidence = 0.5; // No styling detected
|
|
502
|
+
}
|
|
503
|
+
return {
|
|
504
|
+
tokenUsages,
|
|
505
|
+
hardcodedValues,
|
|
506
|
+
hasDesignTokenImport: tokenImports.length > 0,
|
|
507
|
+
usesCSSCustomProperties: cssCustomProperties.length > 0,
|
|
508
|
+
usesThemeObject: themeObjectUsages.length > 0,
|
|
509
|
+
tokenUsageConfidence,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
// ============================================================================
|
|
513
|
+
// Design Tokens Detector Class
|
|
514
|
+
// ============================================================================
|
|
515
|
+
/**
|
|
516
|
+
* Detector for design token usage patterns
|
|
517
|
+
*
|
|
518
|
+
* Identifies design token usage and flags hardcoded values that should
|
|
519
|
+
* use design tokens instead.
|
|
520
|
+
*
|
|
521
|
+
* @requirements 9.1 - THE Styling_Detector SHALL detect design token usage vs hardcoded values
|
|
522
|
+
*/
|
|
523
|
+
export class DesignTokensDetector extends RegexDetector {
|
|
524
|
+
id = 'styling/design-tokens';
|
|
525
|
+
category = 'styling';
|
|
526
|
+
subcategory = 'design-tokens';
|
|
527
|
+
name = 'Design Tokens Detector';
|
|
528
|
+
description = 'Detects design token usage patterns and flags hardcoded values that should use tokens';
|
|
529
|
+
supportedLanguages = ['typescript', 'javascript', 'css'];
|
|
530
|
+
/**
|
|
531
|
+
* Detect design token patterns and violations
|
|
532
|
+
*/
|
|
533
|
+
async detect(context) {
|
|
534
|
+
const patterns = [];
|
|
535
|
+
const violations = [];
|
|
536
|
+
// Analyze the file
|
|
537
|
+
const analysis = analyzeDesignTokens(context.content, context.file);
|
|
538
|
+
// Create pattern matches for token usages
|
|
539
|
+
if (analysis.hasDesignTokenImport) {
|
|
540
|
+
patterns.push(this.createTokenImportPattern(context.file, analysis));
|
|
541
|
+
}
|
|
542
|
+
if (analysis.usesCSSCustomProperties) {
|
|
543
|
+
patterns.push(this.createCSSCustomPropertyPattern(context.file, analysis));
|
|
544
|
+
}
|
|
545
|
+
if (analysis.usesThemeObject) {
|
|
546
|
+
patterns.push(this.createThemeObjectPattern(context.file, analysis));
|
|
547
|
+
}
|
|
548
|
+
// Create violations for hardcoded values
|
|
549
|
+
for (const hardcoded of analysis.hardcodedValues) {
|
|
550
|
+
violations.push(this.createHardcodedValueViolation(hardcoded));
|
|
551
|
+
}
|
|
552
|
+
return this.createResult(patterns, violations, analysis.tokenUsageConfidence);
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Create a pattern match for design token imports
|
|
556
|
+
*/
|
|
557
|
+
createTokenImportPattern(file, analysis) {
|
|
558
|
+
const tokenImports = analysis.tokenUsages.filter(t => t.type === 'design-tokens-import');
|
|
559
|
+
const firstImport = tokenImports[0];
|
|
560
|
+
return {
|
|
561
|
+
patternId: `${this.id}/import`,
|
|
562
|
+
location: {
|
|
563
|
+
file,
|
|
564
|
+
line: firstImport?.line || 1,
|
|
565
|
+
column: firstImport?.column || 1,
|
|
566
|
+
},
|
|
567
|
+
confidence: 1.0,
|
|
568
|
+
isOutlier: false,
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Create a pattern match for CSS custom property usage
|
|
573
|
+
*/
|
|
574
|
+
createCSSCustomPropertyPattern(file, analysis) {
|
|
575
|
+
const cssProps = analysis.tokenUsages.filter(t => t.type === 'css-custom-property');
|
|
576
|
+
const firstProp = cssProps[0];
|
|
577
|
+
return {
|
|
578
|
+
patternId: `${this.id}/css-custom-property`,
|
|
579
|
+
location: {
|
|
580
|
+
file,
|
|
581
|
+
line: firstProp?.line || 1,
|
|
582
|
+
column: firstProp?.column || 1,
|
|
583
|
+
},
|
|
584
|
+
confidence: 1.0,
|
|
585
|
+
isOutlier: false,
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Create a pattern match for theme object usage
|
|
590
|
+
*/
|
|
591
|
+
createThemeObjectPattern(file, analysis) {
|
|
592
|
+
const themeUsages = analysis.tokenUsages.filter(t => t.type === 'theme-object');
|
|
593
|
+
const firstUsage = themeUsages[0];
|
|
594
|
+
return {
|
|
595
|
+
patternId: `${this.id}/theme-object`,
|
|
596
|
+
location: {
|
|
597
|
+
file,
|
|
598
|
+
line: firstUsage?.line || 1,
|
|
599
|
+
column: firstUsage?.column || 1,
|
|
600
|
+
},
|
|
601
|
+
confidence: 1.0,
|
|
602
|
+
isOutlier: false,
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Create a violation for a hardcoded value
|
|
607
|
+
*/
|
|
608
|
+
createHardcodedValueViolation(hardcoded) {
|
|
609
|
+
const typeDescriptions = {
|
|
610
|
+
'color-hex': 'hex color',
|
|
611
|
+
'color-rgb': 'RGB color',
|
|
612
|
+
'color-rgba': 'RGBA color',
|
|
613
|
+
'color-hsl': 'HSL color',
|
|
614
|
+
'color-hsla': 'HSLA color',
|
|
615
|
+
'spacing-px': 'pixel spacing value',
|
|
616
|
+
'spacing-rem': 'rem spacing value',
|
|
617
|
+
'spacing-em': 'em spacing value',
|
|
618
|
+
'font-size': 'font size',
|
|
619
|
+
'border-radius': 'border radius',
|
|
620
|
+
'z-index': 'z-index value',
|
|
621
|
+
};
|
|
622
|
+
const typeDescription = typeDescriptions[hardcoded.type] || 'hardcoded value';
|
|
623
|
+
const propertyInfo = hardcoded.property ? ` in '${hardcoded.property}'` : '';
|
|
624
|
+
const violation = {
|
|
625
|
+
id: `${this.id}-${hardcoded.file}-${hardcoded.line}-${hardcoded.column}`,
|
|
626
|
+
patternId: this.id,
|
|
627
|
+
severity: 'warning',
|
|
628
|
+
file: hardcoded.file,
|
|
629
|
+
range: {
|
|
630
|
+
start: { line: hardcoded.line - 1, character: hardcoded.column - 1 },
|
|
631
|
+
end: { line: hardcoded.endLine - 1, character: hardcoded.endColumn - 1 },
|
|
632
|
+
},
|
|
633
|
+
message: `Hardcoded ${typeDescription} '${hardcoded.value}'${propertyInfo} should use a design token`,
|
|
634
|
+
explanation: `Using hardcoded values instead of design tokens makes it difficult to maintain consistent styling across the application. Design tokens provide a single source of truth for colors, spacing, and other design values.`,
|
|
635
|
+
expected: hardcoded.suggestedToken || 'A design token',
|
|
636
|
+
actual: hardcoded.value,
|
|
637
|
+
aiExplainAvailable: true,
|
|
638
|
+
aiFixAvailable: true,
|
|
639
|
+
firstSeen: new Date(),
|
|
640
|
+
occurrences: 1,
|
|
641
|
+
};
|
|
642
|
+
const quickFix = this.createQuickFixForHardcodedValue(hardcoded);
|
|
643
|
+
if (quickFix !== undefined) {
|
|
644
|
+
violation.quickFix = quickFix;
|
|
645
|
+
}
|
|
646
|
+
return violation;
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Create a quick fix for replacing a hardcoded value with a token
|
|
650
|
+
*/
|
|
651
|
+
createQuickFixForHardcodedValue(hardcoded) {
|
|
652
|
+
// Only provide quick fix if we have a suggested token
|
|
653
|
+
if (!hardcoded.suggestedToken) {
|
|
654
|
+
return undefined;
|
|
655
|
+
}
|
|
656
|
+
// Extract the first suggested token (before "or")
|
|
657
|
+
const suggestedToken = hardcoded.suggestedToken.split(' or ')[0] || hardcoded.suggestedToken;
|
|
658
|
+
// Determine the replacement based on context
|
|
659
|
+
let replacement;
|
|
660
|
+
if (hardcoded.lineContent.includes('var(')) {
|
|
661
|
+
// Already using CSS custom properties, suggest a different custom property
|
|
662
|
+
replacement = `var(--${suggestedToken.replace(/\./g, '-').replace('colors', 'color').replace('spacing', 'spacing')})`;
|
|
663
|
+
}
|
|
664
|
+
else if (hardcoded.lineContent.includes('${') || hardcoded.lineContent.includes('`')) {
|
|
665
|
+
// Template literal context (styled-components, emotion)
|
|
666
|
+
replacement = `\${${suggestedToken}}`;
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
669
|
+
// Default: suggest the token directly
|
|
670
|
+
replacement = suggestedToken;
|
|
671
|
+
}
|
|
672
|
+
return {
|
|
673
|
+
title: `Replace with design token: ${suggestedToken}`,
|
|
674
|
+
kind: 'quickfix',
|
|
675
|
+
edit: {
|
|
676
|
+
changes: {
|
|
677
|
+
[hardcoded.file]: [
|
|
678
|
+
{
|
|
679
|
+
range: {
|
|
680
|
+
start: { line: hardcoded.line - 1, character: hardcoded.column - 1 },
|
|
681
|
+
end: { line: hardcoded.endLine - 1, character: hardcoded.endColumn - 1 },
|
|
682
|
+
},
|
|
683
|
+
newText: replacement,
|
|
684
|
+
},
|
|
685
|
+
],
|
|
686
|
+
},
|
|
687
|
+
},
|
|
688
|
+
isPreferred: true,
|
|
689
|
+
confidence: 0.7,
|
|
690
|
+
preview: `Replace '${hardcoded.value}' with '${replacement}'`,
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Generate a quick fix for a violation
|
|
695
|
+
*/
|
|
696
|
+
generateQuickFix(violation) {
|
|
697
|
+
// Check if this is a hardcoded value violation
|
|
698
|
+
if (!violation.message.includes('Hardcoded')) {
|
|
699
|
+
return null;
|
|
700
|
+
}
|
|
701
|
+
// Extract the value from the message
|
|
702
|
+
const valueMatch = violation.message.match(/Hardcoded [^']+ '([^']+)'/);
|
|
703
|
+
if (!valueMatch || !valueMatch[1]) {
|
|
704
|
+
return null;
|
|
705
|
+
}
|
|
706
|
+
const value = valueMatch[1];
|
|
707
|
+
const isColor = violation.message.includes('color');
|
|
708
|
+
const isSpacing = violation.message.includes('spacing');
|
|
709
|
+
let suggestedToken;
|
|
710
|
+
if (isColor) {
|
|
711
|
+
suggestedToken = suggestColorToken(value);
|
|
712
|
+
}
|
|
713
|
+
else if (isSpacing) {
|
|
714
|
+
suggestedToken = suggestSpacingToken(value);
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
return null;
|
|
718
|
+
}
|
|
719
|
+
const firstSuggestion = suggestedToken.split(' or ')[0] || suggestedToken;
|
|
720
|
+
return {
|
|
721
|
+
title: `Replace with design token: ${firstSuggestion}`,
|
|
722
|
+
kind: 'quickfix',
|
|
723
|
+
edit: {
|
|
724
|
+
changes: {
|
|
725
|
+
[violation.file]: [
|
|
726
|
+
{
|
|
727
|
+
range: violation.range,
|
|
728
|
+
newText: firstSuggestion,
|
|
729
|
+
},
|
|
730
|
+
],
|
|
731
|
+
},
|
|
732
|
+
},
|
|
733
|
+
isPreferred: true,
|
|
734
|
+
confidence: 0.7,
|
|
735
|
+
preview: `Replace '${value}' with '${firstSuggestion}'`,
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
// ============================================================================
|
|
740
|
+
// Factory Function
|
|
741
|
+
// ============================================================================
|
|
742
|
+
/**
|
|
743
|
+
* Create a new DesignTokensDetector instance
|
|
744
|
+
*/
|
|
745
|
+
export function createDesignTokensDetector() {
|
|
746
|
+
return new DesignTokensDetector();
|
|
747
|
+
}
|
|
748
|
+
//# sourceMappingURL=design-tokens.js.map
|