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