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,892 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Class Naming Detector - CSS class naming convention detection
|
|
3
|
+
*
|
|
4
|
+
* Detects CSS class naming patterns including:
|
|
5
|
+
* - BEM pattern (block__element--modifier)
|
|
6
|
+
* - Utility-first pattern (Tailwind-style: flex, items-center, p-4)
|
|
7
|
+
* - CSS Modules pattern (styles.className)
|
|
8
|
+
* - Semantic naming pattern (btn-primary, card-header)
|
|
9
|
+
* - SMACSS/OOCSS patterns
|
|
10
|
+
*
|
|
11
|
+
* Flags inconsistent class naming:
|
|
12
|
+
* - Mixed naming conventions in the same file
|
|
13
|
+
* - Non-standard BEM usage
|
|
14
|
+
* - Inconsistent utility class ordering
|
|
15
|
+
*
|
|
16
|
+
* @requirements 9.5 - THE Styling_Detector SHALL detect CSS class naming conventions (BEM, utility-first)
|
|
17
|
+
*/
|
|
18
|
+
import { RegexDetector } from '../base/index.js';
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Constants
|
|
21
|
+
// ============================================================================
|
|
22
|
+
/**
|
|
23
|
+
* BEM pattern regex
|
|
24
|
+
* Matches: block, block__element, block--modifier, block__element--modifier
|
|
25
|
+
*/
|
|
26
|
+
export const BEM_PATTERN = /\b([a-z][a-z0-9]*(?:-[a-z0-9]+)*)(?:__([a-z][a-z0-9]*(?:-[a-z0-9]+)*))?(?:--([a-z][a-z0-9]*(?:-[a-z0-9]+)*))?\b/gi;
|
|
27
|
+
/**
|
|
28
|
+
* Strict BEM pattern (requires at least __ or --)
|
|
29
|
+
*/
|
|
30
|
+
export const STRICT_BEM_PATTERN = /\b([a-z][a-z0-9]*(?:-[a-z0-9]+)*)(?:__[a-z][a-z0-9]*(?:-[a-z0-9]+)*|--[a-z][a-z0-9]*(?:-[a-z0-9]+)*)+\b/gi;
|
|
31
|
+
/**
|
|
32
|
+
* Invalid BEM patterns (common mistakes)
|
|
33
|
+
*/
|
|
34
|
+
export const INVALID_BEM_PATTERNS = [
|
|
35
|
+
// Double underscore followed by double dash (should be separate)
|
|
36
|
+
/\b[a-z][a-z0-9-]*__[a-z][a-z0-9-]*__[a-z][a-z0-9-]*\b/gi,
|
|
37
|
+
// Triple underscore
|
|
38
|
+
/\b[a-z][a-z0-9-]*___[a-z][a-z0-9-]*\b/gi,
|
|
39
|
+
// Triple dash
|
|
40
|
+
/\b[a-z][a-z0-9-]*---[a-z][a-z0-9-]*\b/gi,
|
|
41
|
+
// Uppercase in BEM (should be lowercase)
|
|
42
|
+
/\b[a-z][a-zA-Z0-9-]*__[A-Z][a-zA-Z0-9-]*\b/g,
|
|
43
|
+
/\b[a-z][a-zA-Z0-9-]*--[A-Z][a-zA-Z0-9-]*\b/g,
|
|
44
|
+
];
|
|
45
|
+
/**
|
|
46
|
+
* Tailwind utility class patterns
|
|
47
|
+
*/
|
|
48
|
+
export const TAILWIND_UTILITY_PATTERNS = [
|
|
49
|
+
// Layout
|
|
50
|
+
/\b(?:flex|grid|block|inline|hidden|container)\b/g,
|
|
51
|
+
/\b(?:flex-row|flex-col|flex-wrap|flex-nowrap|flex-1|flex-auto|flex-initial|flex-none)\b/g,
|
|
52
|
+
/\b(?:grid-cols-\d+|grid-rows-\d+|col-span-\d+|row-span-\d+)\b/g,
|
|
53
|
+
// Spacing
|
|
54
|
+
/\b(?:p|px|py|pt|pr|pb|pl|m|mx|my|mt|mr|mb|ml)-(?:\d+|auto|px)\b/g,
|
|
55
|
+
/\b(?:space-x|space-y|gap|gap-x|gap-y)-\d+\b/g,
|
|
56
|
+
// Sizing
|
|
57
|
+
/\b(?:w|h|min-w|min-h|max-w|max-h)-(?:\d+|full|screen|auto|min|max|fit)\b/g,
|
|
58
|
+
// Typography
|
|
59
|
+
/\b(?:text-(?:xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl))\b/g,
|
|
60
|
+
/\b(?:font-(?:thin|extralight|light|normal|medium|semibold|bold|extrabold|black))\b/g,
|
|
61
|
+
// Colors (simplified)
|
|
62
|
+
/\b(?:text|bg|border|ring)-(?: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,
|
|
63
|
+
// Flexbox alignment
|
|
64
|
+
/\b(?:items|justify|content|self)-(?:start|end|center|between|around|evenly|stretch|baseline)\b/g,
|
|
65
|
+
// Border
|
|
66
|
+
/\b(?:border|border-t|border-r|border-b|border-l)(?:-\d+)?\b/g,
|
|
67
|
+
/\b(?:rounded|rounded-t|rounded-r|rounded-b|rounded-l|rounded-tl|rounded-tr|rounded-bl|rounded-br)(?:-(?:none|sm|md|lg|xl|2xl|3xl|full))?\b/g,
|
|
68
|
+
// Effects
|
|
69
|
+
/\b(?:shadow|shadow-sm|shadow-md|shadow-lg|shadow-xl|shadow-2xl|shadow-inner|shadow-none)\b/g,
|
|
70
|
+
/\b(?:opacity-\d+)\b/g,
|
|
71
|
+
// Positioning
|
|
72
|
+
/\b(?:relative|absolute|fixed|sticky|static)\b/g,
|
|
73
|
+
/\b(?:top|right|bottom|left|inset)-(?:\d+|auto|px|full)\b/g,
|
|
74
|
+
/\b(?:z-\d+|z-auto)\b/g,
|
|
75
|
+
// Display
|
|
76
|
+
/\b(?:overflow|overflow-x|overflow-y)-(?:auto|hidden|visible|scroll)\b/g,
|
|
77
|
+
// Transitions
|
|
78
|
+
/\b(?:transition|transition-all|transition-colors|transition-opacity|transition-shadow|transition-transform)\b/g,
|
|
79
|
+
/\b(?:duration-\d+)\b/g,
|
|
80
|
+
/\b(?:ease-linear|ease-in|ease-out|ease-in-out)\b/g,
|
|
81
|
+
];
|
|
82
|
+
/**
|
|
83
|
+
* CSS Modules pattern
|
|
84
|
+
* Matches: styles.className, styles['class-name'], styles["class-name"]
|
|
85
|
+
*/
|
|
86
|
+
export const CSS_MODULES_PATTERNS = [
|
|
87
|
+
/\bstyles\.([a-zA-Z_][a-zA-Z0-9_]*)\b/g,
|
|
88
|
+
/\bstyles\[['"]([a-zA-Z_][a-zA-Z0-9_-]*)['"]\]/g,
|
|
89
|
+
/\bclasses\.([a-zA-Z_][a-zA-Z0-9_]*)\b/g,
|
|
90
|
+
/\bclasses\[['"]([a-zA-Z_][a-zA-Z0-9_-]*)['"]\]/g,
|
|
91
|
+
/\bcss\.([a-zA-Z_][a-zA-Z0-9_]*)\b/g,
|
|
92
|
+
];
|
|
93
|
+
/**
|
|
94
|
+
* Semantic naming patterns
|
|
95
|
+
* Matches: btn-primary, card-header, nav-item, etc.
|
|
96
|
+
*/
|
|
97
|
+
export const SEMANTIC_NAMING_PATTERNS = [
|
|
98
|
+
// Button patterns
|
|
99
|
+
/\b(?:btn|button)-(?:primary|secondary|tertiary|success|danger|warning|info|light|dark|link|outline|ghost|disabled)\b/gi,
|
|
100
|
+
// Card patterns
|
|
101
|
+
/\b(?:card|panel)-(?:header|body|footer|title|subtitle|content|image|actions)\b/gi,
|
|
102
|
+
// Navigation patterns
|
|
103
|
+
/\b(?:nav|navbar|menu)-(?:item|link|brand|toggle|collapse|dropdown)\b/gi,
|
|
104
|
+
// Form patterns
|
|
105
|
+
/\b(?:form|input|field)-(?:group|control|label|error|help|text|check|radio|select)\b/gi,
|
|
106
|
+
// Layout patterns
|
|
107
|
+
/\b(?:container|wrapper|section|header|footer|sidebar|main|content)-(?:fluid|fixed|full|inner|outer)\b/gi,
|
|
108
|
+
// List patterns
|
|
109
|
+
/\b(?:list|item)-(?:group|item|inline|unstyled|ordered|unordered)\b/gi,
|
|
110
|
+
// Modal/Dialog patterns
|
|
111
|
+
/\b(?:modal|dialog)-(?:header|body|footer|title|content|backdrop|close)\b/gi,
|
|
112
|
+
// Alert patterns
|
|
113
|
+
/\b(?:alert|notification|toast)-(?:success|error|warning|info|primary|secondary|dismissible)\b/gi,
|
|
114
|
+
// Table patterns
|
|
115
|
+
/\b(?:table|row|cell|thead|tbody|tfoot)-(?:header|body|footer|striped|bordered|hover|responsive)\b/gi,
|
|
116
|
+
];
|
|
117
|
+
/**
|
|
118
|
+
* SMACSS patterns
|
|
119
|
+
* Matches: l-*, is-*, has-*, js-*
|
|
120
|
+
*/
|
|
121
|
+
export const SMACSS_PATTERNS = [
|
|
122
|
+
// Layout
|
|
123
|
+
/\bl-[a-z][a-z0-9-]*\b/gi,
|
|
124
|
+
// State
|
|
125
|
+
/\bis-[a-z][a-z0-9-]*\b/gi,
|
|
126
|
+
/\bhas-[a-z][a-z0-9-]*\b/gi,
|
|
127
|
+
// JavaScript hooks
|
|
128
|
+
/\bjs-[a-z][a-z0-9-]*\b/gi,
|
|
129
|
+
];
|
|
130
|
+
/**
|
|
131
|
+
* OOCSS patterns (common object-oriented CSS patterns)
|
|
132
|
+
*/
|
|
133
|
+
export const OOCSS_PATTERNS = [
|
|
134
|
+
// Media object
|
|
135
|
+
/\b(?:media|media-body|media-left|media-right|media-object)\b/gi,
|
|
136
|
+
// Flag object
|
|
137
|
+
/\b(?:flag|flag-body|flag-image)\b/gi,
|
|
138
|
+
// Box object
|
|
139
|
+
/\b(?:box|box-header|box-body|box-footer)\b/gi,
|
|
140
|
+
];
|
|
141
|
+
/**
|
|
142
|
+
* File patterns to exclude from class naming detection
|
|
143
|
+
*/
|
|
144
|
+
export const EXCLUDED_FILE_PATTERNS = [
|
|
145
|
+
/\.test\.[jt]sx?$/,
|
|
146
|
+
/\.spec\.[jt]sx?$/,
|
|
147
|
+
/\.stories\.[jt]sx?$/,
|
|
148
|
+
/\.config\.[jt]s$/,
|
|
149
|
+
/tailwind\.config/,
|
|
150
|
+
];
|
|
151
|
+
/**
|
|
152
|
+
* Recommended utility class ordering (Tailwind convention)
|
|
153
|
+
*/
|
|
154
|
+
export const UTILITY_CLASS_ORDER = [
|
|
155
|
+
'container',
|
|
156
|
+
'position',
|
|
157
|
+
'display',
|
|
158
|
+
'flex',
|
|
159
|
+
'grid',
|
|
160
|
+
'width',
|
|
161
|
+
'height',
|
|
162
|
+
'margin',
|
|
163
|
+
'padding',
|
|
164
|
+
'border',
|
|
165
|
+
'background',
|
|
166
|
+
'text',
|
|
167
|
+
'font',
|
|
168
|
+
'color',
|
|
169
|
+
'opacity',
|
|
170
|
+
'shadow',
|
|
171
|
+
'transition',
|
|
172
|
+
'animation',
|
|
173
|
+
];
|
|
174
|
+
// ============================================================================
|
|
175
|
+
// Helper Functions
|
|
176
|
+
// ============================================================================
|
|
177
|
+
/**
|
|
178
|
+
* Check if a file should be excluded from class naming detection
|
|
179
|
+
*/
|
|
180
|
+
export function shouldExcludeFile(filePath) {
|
|
181
|
+
return EXCLUDED_FILE_PATTERNS.some(pattern => pattern.test(filePath));
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Check if a position is inside a comment
|
|
185
|
+
*/
|
|
186
|
+
function isInsideComment(content, index) {
|
|
187
|
+
const beforeIndex = content.slice(0, index);
|
|
188
|
+
// Check for single-line comment
|
|
189
|
+
const lastNewline = beforeIndex.lastIndexOf('\n');
|
|
190
|
+
const currentLine = beforeIndex.slice(lastNewline + 1);
|
|
191
|
+
if (currentLine.includes('//')) {
|
|
192
|
+
const commentStart = currentLine.indexOf('//');
|
|
193
|
+
const positionInLine = index - lastNewline - 1;
|
|
194
|
+
if (positionInLine > commentStart) {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Check for multi-line comment
|
|
199
|
+
const lastBlockCommentStart = beforeIndex.lastIndexOf('/*');
|
|
200
|
+
const lastBlockCommentEnd = beforeIndex.lastIndexOf('*/');
|
|
201
|
+
if (lastBlockCommentStart > lastBlockCommentEnd) {
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Check if a class name follows BEM convention
|
|
208
|
+
*/
|
|
209
|
+
export function isBEMClassName(className) {
|
|
210
|
+
// BEM: block__element--modifier
|
|
211
|
+
return /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*(?:__[a-z][a-z0-9]*(?:-[a-z0-9]+)*)?(?:--[a-z][a-z0-9]*(?:-[a-z0-9]+)*)?$/i.test(className);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Check if a class name is a Tailwind utility class
|
|
215
|
+
*/
|
|
216
|
+
export function isTailwindUtilityClass(className) {
|
|
217
|
+
for (const pattern of TAILWIND_UTILITY_PATTERNS) {
|
|
218
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
219
|
+
if (regex.test(className)) {
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Check if a class name follows semantic naming
|
|
227
|
+
*/
|
|
228
|
+
export function isSemanticClassName(className) {
|
|
229
|
+
for (const pattern of SEMANTIC_NAMING_PATTERNS) {
|
|
230
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
231
|
+
if (regex.test(className)) {
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Check if a class name follows SMACSS convention
|
|
239
|
+
*/
|
|
240
|
+
export function isSMACSClassName(className) {
|
|
241
|
+
for (const pattern of SMACSS_PATTERNS) {
|
|
242
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
243
|
+
if (regex.test(className)) {
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Validate BEM class name and return issues
|
|
251
|
+
*/
|
|
252
|
+
export function validateBEMClassName(className) {
|
|
253
|
+
// Check for multiple element separators
|
|
254
|
+
if ((className.match(/__/g) || []).length > 1) {
|
|
255
|
+
return 'BEM class should have at most one element separator (__)';
|
|
256
|
+
}
|
|
257
|
+
// Check for uppercase letters
|
|
258
|
+
if (/[A-Z]/.test(className)) {
|
|
259
|
+
return 'BEM class names should be lowercase';
|
|
260
|
+
}
|
|
261
|
+
// Check for invalid characters
|
|
262
|
+
if (/[^a-z0-9_-]/i.test(className)) {
|
|
263
|
+
return 'BEM class names should only contain lowercase letters, numbers, hyphens, and underscores';
|
|
264
|
+
}
|
|
265
|
+
// Check for triple underscore or dash
|
|
266
|
+
if (/___/.test(className) || /---/.test(className)) {
|
|
267
|
+
return 'BEM class names should not have triple underscores or dashes';
|
|
268
|
+
}
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Detect BEM patterns in content
|
|
273
|
+
*/
|
|
274
|
+
export function detectBEMPatterns(content, file) {
|
|
275
|
+
const results = [];
|
|
276
|
+
const lines = content.split('\n');
|
|
277
|
+
const regex = new RegExp(STRICT_BEM_PATTERN.source, STRICT_BEM_PATTERN.flags);
|
|
278
|
+
let match;
|
|
279
|
+
while ((match = regex.exec(content)) !== null) {
|
|
280
|
+
// Skip if inside a comment
|
|
281
|
+
if (isInsideComment(content, match.index)) {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
const beforeMatch = content.slice(0, match.index);
|
|
285
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
286
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
287
|
+
const column = match.index - lastNewline;
|
|
288
|
+
results.push({
|
|
289
|
+
type: 'bem',
|
|
290
|
+
file,
|
|
291
|
+
line: lineNumber,
|
|
292
|
+
column,
|
|
293
|
+
matchedText: match[0],
|
|
294
|
+
classNames: [match[0]],
|
|
295
|
+
context: lines[lineNumber - 1] || '',
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return results;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Detect utility-first (Tailwind) patterns in content
|
|
302
|
+
*/
|
|
303
|
+
export function detectUtilityFirstPatterns(content, file) {
|
|
304
|
+
const results = [];
|
|
305
|
+
const lines = content.split('\n');
|
|
306
|
+
const seenMatches = new Set();
|
|
307
|
+
for (const pattern of TAILWIND_UTILITY_PATTERNS) {
|
|
308
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
309
|
+
let match;
|
|
310
|
+
while ((match = regex.exec(content)) !== null) {
|
|
311
|
+
const key = `${match.index}-${match[0]}`;
|
|
312
|
+
if (seenMatches.has(key))
|
|
313
|
+
continue;
|
|
314
|
+
seenMatches.add(key);
|
|
315
|
+
// Skip if inside a comment
|
|
316
|
+
if (isInsideComment(content, match.index)) {
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
const beforeMatch = content.slice(0, match.index);
|
|
320
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
321
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
322
|
+
const column = match.index - lastNewline;
|
|
323
|
+
results.push({
|
|
324
|
+
type: 'utility-first',
|
|
325
|
+
file,
|
|
326
|
+
line: lineNumber,
|
|
327
|
+
column,
|
|
328
|
+
matchedText: match[0],
|
|
329
|
+
classNames: [match[0]],
|
|
330
|
+
context: lines[lineNumber - 1] || '',
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return results;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Detect CSS Modules patterns in content
|
|
338
|
+
*/
|
|
339
|
+
export function detectCSSModulesPatterns(content, file) {
|
|
340
|
+
const results = [];
|
|
341
|
+
const lines = content.split('\n');
|
|
342
|
+
for (const pattern of CSS_MODULES_PATTERNS) {
|
|
343
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
344
|
+
let match;
|
|
345
|
+
while ((match = regex.exec(content)) !== null) {
|
|
346
|
+
// Skip if inside a comment
|
|
347
|
+
if (isInsideComment(content, match.index)) {
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
const beforeMatch = content.slice(0, match.index);
|
|
351
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
352
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
353
|
+
const column = match.index - lastNewline;
|
|
354
|
+
results.push({
|
|
355
|
+
type: 'css-modules',
|
|
356
|
+
file,
|
|
357
|
+
line: lineNumber,
|
|
358
|
+
column,
|
|
359
|
+
matchedText: match[0],
|
|
360
|
+
classNames: [match[1] || match[0]],
|
|
361
|
+
context: lines[lineNumber - 1] || '',
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return results;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Detect semantic naming patterns in content
|
|
369
|
+
*/
|
|
370
|
+
export function detectSemanticPatterns(content, file) {
|
|
371
|
+
const results = [];
|
|
372
|
+
const lines = content.split('\n');
|
|
373
|
+
for (const pattern of SEMANTIC_NAMING_PATTERNS) {
|
|
374
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
375
|
+
let match;
|
|
376
|
+
while ((match = regex.exec(content)) !== null) {
|
|
377
|
+
// Skip if inside a comment
|
|
378
|
+
if (isInsideComment(content, match.index)) {
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
381
|
+
const beforeMatch = content.slice(0, match.index);
|
|
382
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
383
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
384
|
+
const column = match.index - lastNewline;
|
|
385
|
+
results.push({
|
|
386
|
+
type: 'semantic',
|
|
387
|
+
file,
|
|
388
|
+
line: lineNumber,
|
|
389
|
+
column,
|
|
390
|
+
matchedText: match[0],
|
|
391
|
+
classNames: [match[0]],
|
|
392
|
+
context: lines[lineNumber - 1] || '',
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return results;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Detect SMACSS patterns in content
|
|
400
|
+
*/
|
|
401
|
+
export function detectSMACSPatterns(content, file) {
|
|
402
|
+
const results = [];
|
|
403
|
+
const lines = content.split('\n');
|
|
404
|
+
for (const pattern of SMACSS_PATTERNS) {
|
|
405
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
406
|
+
let match;
|
|
407
|
+
while ((match = regex.exec(content)) !== null) {
|
|
408
|
+
// Skip if inside a comment
|
|
409
|
+
if (isInsideComment(content, match.index)) {
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const beforeMatch = content.slice(0, match.index);
|
|
413
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
414
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
415
|
+
const column = match.index - lastNewline;
|
|
416
|
+
results.push({
|
|
417
|
+
type: 'smacss',
|
|
418
|
+
file,
|
|
419
|
+
line: lineNumber,
|
|
420
|
+
column,
|
|
421
|
+
matchedText: match[0],
|
|
422
|
+
classNames: [match[0]],
|
|
423
|
+
context: lines[lineNumber - 1] || '',
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return results;
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Detect invalid BEM patterns
|
|
431
|
+
*/
|
|
432
|
+
export function detectInvalidBEMPatterns(content, file) {
|
|
433
|
+
const results = [];
|
|
434
|
+
const lines = content.split('\n');
|
|
435
|
+
for (const pattern of INVALID_BEM_PATTERNS) {
|
|
436
|
+
const regex = new RegExp(pattern.source, pattern.flags);
|
|
437
|
+
let match;
|
|
438
|
+
while ((match = regex.exec(content)) !== null) {
|
|
439
|
+
// Skip if inside a comment
|
|
440
|
+
if (isInsideComment(content, match.index)) {
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
const beforeMatch = content.slice(0, match.index);
|
|
444
|
+
const lineNumber = beforeMatch.split('\n').length;
|
|
445
|
+
const lastNewline = beforeMatch.lastIndexOf('\n');
|
|
446
|
+
const column = match.index - lastNewline;
|
|
447
|
+
const endColumn = column + match[0].length;
|
|
448
|
+
const issue = validateBEMClassName(match[0]) || 'Invalid BEM class name format';
|
|
449
|
+
results.push({
|
|
450
|
+
type: 'invalid-bem',
|
|
451
|
+
file,
|
|
452
|
+
line: lineNumber,
|
|
453
|
+
column,
|
|
454
|
+
endLine: lineNumber,
|
|
455
|
+
endColumn,
|
|
456
|
+
classNames: [match[0]],
|
|
457
|
+
issue,
|
|
458
|
+
suggestedFix: suggestBEMFix(match[0]),
|
|
459
|
+
lineContent: lines[lineNumber - 1] || '',
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return results;
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Detect mixed naming conventions in a file
|
|
467
|
+
*/
|
|
468
|
+
export function detectMixedConventions(patterns, file) {
|
|
469
|
+
const results = [];
|
|
470
|
+
// Count patterns by type
|
|
471
|
+
const typeCounts = {
|
|
472
|
+
'bem': 0,
|
|
473
|
+
'utility-first': 0,
|
|
474
|
+
'css-modules': 0,
|
|
475
|
+
'semantic': 0,
|
|
476
|
+
'smacss': 0,
|
|
477
|
+
'oocss': 0,
|
|
478
|
+
};
|
|
479
|
+
for (const pattern of patterns) {
|
|
480
|
+
typeCounts[pattern.type]++;
|
|
481
|
+
}
|
|
482
|
+
// Find the dominant convention
|
|
483
|
+
const sortedTypes = Object.entries(typeCounts)
|
|
484
|
+
.filter(([_, count]) => count > 0)
|
|
485
|
+
.sort((a, b) => b[1] - a[1]);
|
|
486
|
+
if (sortedTypes.length <= 1) {
|
|
487
|
+
return results; // No mixed conventions
|
|
488
|
+
}
|
|
489
|
+
const dominantType = sortedTypes[0]?.[0];
|
|
490
|
+
const dominantCount = sortedTypes[0]?.[1] || 0;
|
|
491
|
+
// Flag patterns that don't match the dominant convention
|
|
492
|
+
// Only flag if there's a clear dominant pattern (>60% of patterns)
|
|
493
|
+
const totalPatterns = patterns.length;
|
|
494
|
+
if (dominantCount / totalPatterns < 0.6) {
|
|
495
|
+
// No clear dominant pattern, flag all as mixed
|
|
496
|
+
const firstPattern = patterns[0];
|
|
497
|
+
if (firstPattern) {
|
|
498
|
+
results.push({
|
|
499
|
+
type: 'mixed-conventions',
|
|
500
|
+
file,
|
|
501
|
+
line: firstPattern.line,
|
|
502
|
+
column: firstPattern.column,
|
|
503
|
+
endLine: firstPattern.line,
|
|
504
|
+
endColumn: firstPattern.column + firstPattern.matchedText.length,
|
|
505
|
+
classNames: patterns.map(p => p.matchedText),
|
|
506
|
+
issue: `File uses multiple naming conventions: ${sortedTypes.map(([t, c]) => `${t} (${c})`).join(', ')}`,
|
|
507
|
+
suggestedFix: `Consider standardizing on one naming convention (most common: ${dominantType})`,
|
|
508
|
+
lineContent: firstPattern.context || '',
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
// Flag minority patterns
|
|
514
|
+
for (const pattern of patterns) {
|
|
515
|
+
if (pattern.type !== dominantType) {
|
|
516
|
+
results.push({
|
|
517
|
+
type: 'mixed-conventions',
|
|
518
|
+
file,
|
|
519
|
+
line: pattern.line,
|
|
520
|
+
column: pattern.column,
|
|
521
|
+
endLine: pattern.line,
|
|
522
|
+
endColumn: pattern.column + pattern.matchedText.length,
|
|
523
|
+
classNames: [pattern.matchedText],
|
|
524
|
+
issue: `Class '${pattern.matchedText}' uses ${pattern.type} convention, but file predominantly uses ${dominantType}`,
|
|
525
|
+
suggestedFix: `Consider converting to ${dominantType} convention`,
|
|
526
|
+
lineContent: pattern.context || '',
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
return results;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Suggest a BEM fix for an invalid class name
|
|
535
|
+
*/
|
|
536
|
+
export function suggestBEMFix(className) {
|
|
537
|
+
// Convert to lowercase
|
|
538
|
+
let fixed = className.toLowerCase();
|
|
539
|
+
// Replace triple underscores/dashes with double
|
|
540
|
+
fixed = fixed.replace(/___/g, '__').replace(/---/g, '--');
|
|
541
|
+
// Remove extra element separators
|
|
542
|
+
const parts = fixed.split('__');
|
|
543
|
+
if (parts.length > 2) {
|
|
544
|
+
fixed = `${parts[0]}__${parts.slice(1).join('-')}`;
|
|
545
|
+
}
|
|
546
|
+
return fixed;
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Determine the dominant naming convention
|
|
550
|
+
*/
|
|
551
|
+
export function getDominantConvention(patterns) {
|
|
552
|
+
if (patterns.length === 0)
|
|
553
|
+
return null;
|
|
554
|
+
const typeCounts = {
|
|
555
|
+
'bem': 0,
|
|
556
|
+
'utility-first': 0,
|
|
557
|
+
'css-modules': 0,
|
|
558
|
+
'semantic': 0,
|
|
559
|
+
'smacss': 0,
|
|
560
|
+
'oocss': 0,
|
|
561
|
+
};
|
|
562
|
+
for (const pattern of patterns) {
|
|
563
|
+
typeCounts[pattern.type]++;
|
|
564
|
+
}
|
|
565
|
+
const sortedTypes = Object.entries(typeCounts)
|
|
566
|
+
.filter(([_, count]) => count > 0)
|
|
567
|
+
.sort((a, b) => b[1] - a[1]);
|
|
568
|
+
return sortedTypes[0]?.[0] || null;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Analyze class naming patterns in a file
|
|
572
|
+
*/
|
|
573
|
+
export function analyzeClassNaming(content, file) {
|
|
574
|
+
// Skip excluded files
|
|
575
|
+
if (shouldExcludeFile(file)) {
|
|
576
|
+
return {
|
|
577
|
+
patterns: [],
|
|
578
|
+
violations: [],
|
|
579
|
+
usesBEM: false,
|
|
580
|
+
usesUtilityFirst: false,
|
|
581
|
+
usesCSSModules: false,
|
|
582
|
+
usesSemantic: false,
|
|
583
|
+
usesSMACSS: false,
|
|
584
|
+
dominantConvention: null,
|
|
585
|
+
namingConsistencyConfidence: 1.0,
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
// Detect all patterns
|
|
589
|
+
const bemPatterns = detectBEMPatterns(content, file);
|
|
590
|
+
const utilityPatterns = detectUtilityFirstPatterns(content, file);
|
|
591
|
+
const cssModulesPatterns = detectCSSModulesPatterns(content, file);
|
|
592
|
+
const semanticPatterns = detectSemanticPatterns(content, file);
|
|
593
|
+
const smacssPatterns = detectSMACSPatterns(content, file);
|
|
594
|
+
const allPatterns = [
|
|
595
|
+
...bemPatterns,
|
|
596
|
+
...utilityPatterns,
|
|
597
|
+
...cssModulesPatterns,
|
|
598
|
+
...semanticPatterns,
|
|
599
|
+
...smacssPatterns,
|
|
600
|
+
];
|
|
601
|
+
// Detect violations
|
|
602
|
+
const invalidBEMViolations = detectInvalidBEMPatterns(content, file);
|
|
603
|
+
const mixedConventionViolations = detectMixedConventions(allPatterns, file);
|
|
604
|
+
const allViolations = [
|
|
605
|
+
...invalidBEMViolations,
|
|
606
|
+
...mixedConventionViolations,
|
|
607
|
+
];
|
|
608
|
+
// Calculate confidence
|
|
609
|
+
const hasPatterns = allPatterns.length > 0;
|
|
610
|
+
const hasViolations = allViolations.length > 0;
|
|
611
|
+
let namingConsistencyConfidence = 0;
|
|
612
|
+
if (hasPatterns && !hasViolations) {
|
|
613
|
+
namingConsistencyConfidence = 1.0;
|
|
614
|
+
}
|
|
615
|
+
else if (hasPatterns && hasViolations) {
|
|
616
|
+
const ratio = allPatterns.length / (allPatterns.length + allViolations.length);
|
|
617
|
+
namingConsistencyConfidence = ratio;
|
|
618
|
+
}
|
|
619
|
+
else if (!hasPatterns && hasViolations) {
|
|
620
|
+
namingConsistencyConfidence = 0;
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
namingConsistencyConfidence = 0.5; // No class naming detected
|
|
624
|
+
}
|
|
625
|
+
return {
|
|
626
|
+
patterns: allPatterns,
|
|
627
|
+
violations: allViolations,
|
|
628
|
+
usesBEM: bemPatterns.length > 0,
|
|
629
|
+
usesUtilityFirst: utilityPatterns.length > 0,
|
|
630
|
+
usesCSSModules: cssModulesPatterns.length > 0,
|
|
631
|
+
usesSemantic: semanticPatterns.length > 0,
|
|
632
|
+
usesSMACSS: smacssPatterns.length > 0,
|
|
633
|
+
dominantConvention: getDominantConvention(allPatterns),
|
|
634
|
+
namingConsistencyConfidence,
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
// ============================================================================
|
|
638
|
+
// Class Naming Detector Class
|
|
639
|
+
// ============================================================================
|
|
640
|
+
/**
|
|
641
|
+
* Detector for CSS class naming conventions
|
|
642
|
+
*
|
|
643
|
+
* Identifies class naming patterns (BEM, utility-first, CSS Modules, semantic)
|
|
644
|
+
* and flags inconsistent naming conventions.
|
|
645
|
+
*
|
|
646
|
+
* @requirements 9.5 - THE Styling_Detector SHALL detect CSS class naming conventions (BEM, utility-first)
|
|
647
|
+
*/
|
|
648
|
+
export class ClassNamingDetector extends RegexDetector {
|
|
649
|
+
id = 'styling/class-naming';
|
|
650
|
+
category = 'styling';
|
|
651
|
+
subcategory = 'class-naming';
|
|
652
|
+
name = 'Class Naming Detector';
|
|
653
|
+
description = 'Detects CSS class naming conventions (BEM, utility-first, CSS Modules) and flags inconsistent naming';
|
|
654
|
+
supportedLanguages = ['typescript', 'javascript', 'css'];
|
|
655
|
+
/**
|
|
656
|
+
* Detect class naming patterns and violations
|
|
657
|
+
*/
|
|
658
|
+
async detect(context) {
|
|
659
|
+
const patterns = [];
|
|
660
|
+
const violations = [];
|
|
661
|
+
// Analyze the file
|
|
662
|
+
const analysis = analyzeClassNaming(context.content, context.file);
|
|
663
|
+
// Create pattern matches for naming conventions
|
|
664
|
+
if (analysis.usesBEM) {
|
|
665
|
+
patterns.push(this.createBEMPattern(context.file, analysis));
|
|
666
|
+
}
|
|
667
|
+
if (analysis.usesUtilityFirst) {
|
|
668
|
+
patterns.push(this.createUtilityFirstPattern(context.file, analysis));
|
|
669
|
+
}
|
|
670
|
+
if (analysis.usesCSSModules) {
|
|
671
|
+
patterns.push(this.createCSSModulesPattern(context.file, analysis));
|
|
672
|
+
}
|
|
673
|
+
if (analysis.usesSemantic) {
|
|
674
|
+
patterns.push(this.createSemanticPattern(context.file, analysis));
|
|
675
|
+
}
|
|
676
|
+
if (analysis.usesSMACSS) {
|
|
677
|
+
patterns.push(this.createSMACSPattern(context.file, analysis));
|
|
678
|
+
}
|
|
679
|
+
// Create violations
|
|
680
|
+
for (const violation of analysis.violations) {
|
|
681
|
+
violations.push(this.createClassNamingViolation(violation));
|
|
682
|
+
}
|
|
683
|
+
return this.createResult(patterns, violations, analysis.namingConsistencyConfidence);
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Create a pattern match for BEM usage
|
|
687
|
+
*/
|
|
688
|
+
createBEMPattern(file, analysis) {
|
|
689
|
+
const bemPatterns = analysis.patterns.filter(p => p.type === 'bem');
|
|
690
|
+
const firstPattern = bemPatterns[0];
|
|
691
|
+
return {
|
|
692
|
+
patternId: `${this.id}/bem`,
|
|
693
|
+
location: {
|
|
694
|
+
file,
|
|
695
|
+
line: firstPattern?.line || 1,
|
|
696
|
+
column: firstPattern?.column || 1,
|
|
697
|
+
},
|
|
698
|
+
confidence: 1.0,
|
|
699
|
+
isOutlier: false,
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Create a pattern match for utility-first usage
|
|
704
|
+
*/
|
|
705
|
+
createUtilityFirstPattern(file, analysis) {
|
|
706
|
+
const utilityPatterns = analysis.patterns.filter(p => p.type === 'utility-first');
|
|
707
|
+
const firstPattern = utilityPatterns[0];
|
|
708
|
+
return {
|
|
709
|
+
patternId: `${this.id}/utility-first`,
|
|
710
|
+
location: {
|
|
711
|
+
file,
|
|
712
|
+
line: firstPattern?.line || 1,
|
|
713
|
+
column: firstPattern?.column || 1,
|
|
714
|
+
},
|
|
715
|
+
confidence: 1.0,
|
|
716
|
+
isOutlier: false,
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Create a pattern match for CSS Modules usage
|
|
721
|
+
*/
|
|
722
|
+
createCSSModulesPattern(file, analysis) {
|
|
723
|
+
const cssModulesPatterns = analysis.patterns.filter(p => p.type === 'css-modules');
|
|
724
|
+
const firstPattern = cssModulesPatterns[0];
|
|
725
|
+
return {
|
|
726
|
+
patternId: `${this.id}/css-modules`,
|
|
727
|
+
location: {
|
|
728
|
+
file,
|
|
729
|
+
line: firstPattern?.line || 1,
|
|
730
|
+
column: firstPattern?.column || 1,
|
|
731
|
+
},
|
|
732
|
+
confidence: 1.0,
|
|
733
|
+
isOutlier: false,
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* Create a pattern match for semantic naming usage
|
|
738
|
+
*/
|
|
739
|
+
createSemanticPattern(file, analysis) {
|
|
740
|
+
const semanticPatterns = analysis.patterns.filter(p => p.type === 'semantic');
|
|
741
|
+
const firstPattern = semanticPatterns[0];
|
|
742
|
+
return {
|
|
743
|
+
patternId: `${this.id}/semantic`,
|
|
744
|
+
location: {
|
|
745
|
+
file,
|
|
746
|
+
line: firstPattern?.line || 1,
|
|
747
|
+
column: firstPattern?.column || 1,
|
|
748
|
+
},
|
|
749
|
+
confidence: 1.0,
|
|
750
|
+
isOutlier: false,
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Create a pattern match for SMACSS usage
|
|
755
|
+
*/
|
|
756
|
+
createSMACSPattern(file, analysis) {
|
|
757
|
+
const smacssPatterns = analysis.patterns.filter(p => p.type === 'smacss');
|
|
758
|
+
const firstPattern = smacssPatterns[0];
|
|
759
|
+
return {
|
|
760
|
+
patternId: `${this.id}/smacss`,
|
|
761
|
+
location: {
|
|
762
|
+
file,
|
|
763
|
+
line: firstPattern?.line || 1,
|
|
764
|
+
column: firstPattern?.column || 1,
|
|
765
|
+
},
|
|
766
|
+
confidence: 1.0,
|
|
767
|
+
isOutlier: false,
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Create a violation for a class naming issue
|
|
772
|
+
*/
|
|
773
|
+
createClassNamingViolation(info) {
|
|
774
|
+
const typeDescriptions = {
|
|
775
|
+
'mixed-conventions': 'Mixed naming conventions',
|
|
776
|
+
'invalid-bem': 'Invalid BEM class name',
|
|
777
|
+
'inconsistent-ordering': 'Inconsistent utility class ordering',
|
|
778
|
+
'non-semantic-name': 'Non-semantic class name',
|
|
779
|
+
};
|
|
780
|
+
const typeDescription = typeDescriptions[info.type] || 'Class naming issue';
|
|
781
|
+
const violation = {
|
|
782
|
+
id: `${this.id}-${info.file}-${info.line}-${info.column}`,
|
|
783
|
+
patternId: this.id,
|
|
784
|
+
severity: info.type === 'invalid-bem' ? 'warning' : 'info',
|
|
785
|
+
file: info.file,
|
|
786
|
+
range: {
|
|
787
|
+
start: { line: info.line - 1, character: info.column - 1 },
|
|
788
|
+
end: { line: info.endLine - 1, character: info.endColumn - 1 },
|
|
789
|
+
},
|
|
790
|
+
message: `${typeDescription}: ${info.issue}`,
|
|
791
|
+
explanation: this.getExplanationForViolationType(info.type),
|
|
792
|
+
expected: info.suggestedFix || 'Consistent class naming convention',
|
|
793
|
+
actual: info.classNames.join(', '),
|
|
794
|
+
aiExplainAvailable: true,
|
|
795
|
+
aiFixAvailable: info.type === 'invalid-bem',
|
|
796
|
+
firstSeen: new Date(),
|
|
797
|
+
occurrences: 1,
|
|
798
|
+
};
|
|
799
|
+
const quickFix = this.createQuickFixForViolation(info);
|
|
800
|
+
if (quickFix !== undefined) {
|
|
801
|
+
violation.quickFix = quickFix;
|
|
802
|
+
}
|
|
803
|
+
return violation;
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Get explanation for a violation type
|
|
807
|
+
*/
|
|
808
|
+
getExplanationForViolationType(type) {
|
|
809
|
+
switch (type) {
|
|
810
|
+
case 'mixed-conventions':
|
|
811
|
+
return 'Using multiple naming conventions in the same file makes the codebase harder to maintain. Choose one convention and apply it consistently.';
|
|
812
|
+
case 'invalid-bem':
|
|
813
|
+
return 'BEM (Block Element Modifier) naming should follow the pattern: block__element--modifier. Class names should be lowercase with hyphens for multi-word names.';
|
|
814
|
+
case 'inconsistent-ordering':
|
|
815
|
+
return 'Utility classes should follow a consistent ordering (e.g., layout, spacing, typography, colors) for better readability.';
|
|
816
|
+
case 'non-semantic-name':
|
|
817
|
+
return 'Class names should describe the purpose or meaning of the element, not its appearance.';
|
|
818
|
+
default:
|
|
819
|
+
return 'Consistent class naming improves code maintainability and readability.';
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* Create a quick fix for a class naming violation
|
|
824
|
+
*/
|
|
825
|
+
createQuickFixForViolation(info) {
|
|
826
|
+
if (info.type !== 'invalid-bem' || !info.suggestedFix) {
|
|
827
|
+
return undefined;
|
|
828
|
+
}
|
|
829
|
+
return {
|
|
830
|
+
title: `Fix BEM class name: ${info.suggestedFix}`,
|
|
831
|
+
kind: 'quickfix',
|
|
832
|
+
edit: {
|
|
833
|
+
changes: {
|
|
834
|
+
[info.file]: [
|
|
835
|
+
{
|
|
836
|
+
range: {
|
|
837
|
+
start: { line: info.line - 1, character: info.column - 1 },
|
|
838
|
+
end: { line: info.endLine - 1, character: info.endColumn - 1 },
|
|
839
|
+
},
|
|
840
|
+
newText: info.suggestedFix,
|
|
841
|
+
},
|
|
842
|
+
],
|
|
843
|
+
},
|
|
844
|
+
},
|
|
845
|
+
isPreferred: true,
|
|
846
|
+
confidence: 0.8,
|
|
847
|
+
preview: `Replace '${info.classNames[0]}' with '${info.suggestedFix}'`,
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
/**
|
|
851
|
+
* Generate a quick fix for a violation
|
|
852
|
+
*/
|
|
853
|
+
generateQuickFix(violation) {
|
|
854
|
+
// Check if this is a BEM violation
|
|
855
|
+
if (!violation.message.includes('BEM')) {
|
|
856
|
+
return null;
|
|
857
|
+
}
|
|
858
|
+
// Extract the class name from the message
|
|
859
|
+
const classMatch = violation.actual;
|
|
860
|
+
if (!classMatch) {
|
|
861
|
+
return null;
|
|
862
|
+
}
|
|
863
|
+
const suggestedFix = suggestBEMFix(classMatch);
|
|
864
|
+
return {
|
|
865
|
+
title: `Fix BEM class name: ${suggestedFix}`,
|
|
866
|
+
kind: 'quickfix',
|
|
867
|
+
edit: {
|
|
868
|
+
changes: {
|
|
869
|
+
[violation.file]: [
|
|
870
|
+
{
|
|
871
|
+
range: violation.range,
|
|
872
|
+
newText: suggestedFix,
|
|
873
|
+
},
|
|
874
|
+
],
|
|
875
|
+
},
|
|
876
|
+
},
|
|
877
|
+
isPreferred: true,
|
|
878
|
+
confidence: 0.8,
|
|
879
|
+
preview: `Replace '${classMatch}' with '${suggestedFix}'`,
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
// ============================================================================
|
|
884
|
+
// Factory Function
|
|
885
|
+
// ============================================================================
|
|
886
|
+
/**
|
|
887
|
+
* Create a new ClassNamingDetector instance
|
|
888
|
+
*/
|
|
889
|
+
export function createClassNamingDetector() {
|
|
890
|
+
return new ClassNamingDetector();
|
|
891
|
+
}
|
|
892
|
+
//# sourceMappingURL=class-naming.js.map
|