@mocoto/mahoraga 0.14.1 → 0.14.3

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 (306) hide show
  1. package/README.md +0 -34
  2. package/dist/analysts/architects/analyst-structure.js +20 -20
  3. package/dist/analysts/architects/archetypes-custom.js +16 -19
  4. package/dist/analysts/architects/detector-archetypes.js +43 -36
  5. package/dist/analysts/architects/orchestrator-archetypes.js +3 -3
  6. package/dist/analysts/architects/signals-project-advanced.js +26 -28
  7. package/dist/analysts/architects/signals-project.js +2 -2
  8. package/dist/analysts/architects/strategist-structure.js +47 -66
  9. package/dist/analysts/azure-pipelines/analysts/analyst-azure.js +41 -35
  10. package/dist/analysts/azure-pipelines/corrections/correction-azure.js +22 -19
  11. package/dist/analysts/azure-pipelines/detectors/detector-azure-performance.js +21 -18
  12. package/dist/analysts/azure-pipelines/detectors/detector-azure-security.js +25 -20
  13. package/dist/analysts/azure-pipelines/detectors/detector-azure-structure.js +39 -40
  14. package/dist/analysts/azure-pipelines/scorers/scorer-azure.js +10 -7
  15. package/dist/analysts/circleci/analysts/analyst-circleci.js +33 -27
  16. package/dist/analysts/circleci/corrections/correction-circleci.js +22 -20
  17. package/dist/analysts/circleci/detectors/detector-circleci-performance.js +23 -19
  18. package/dist/analysts/circleci/detectors/detector-circleci-security.js +78 -82
  19. package/dist/analysts/circleci/detectors/detector-circleci-structure.js +22 -22
  20. package/dist/analysts/converters/convert-registry.js +1 -1
  21. package/dist/analysts/converters/engines/converter-gha-to-gitlab.js +17 -15
  22. package/dist/analysts/converters/index.js +1 -1
  23. package/dist/analysts/corrections/analyst-quick-fixes.js +25 -28
  24. package/dist/analysts/corrections/analyst-scoring.js +24 -21
  25. package/dist/analysts/corrections/auto-fix-engine.js +1 -1
  26. package/dist/analysts/corrections/corrector-structure.js +43 -42
  27. package/dist/analysts/corrections/fix-alias-imports.js +10 -6
  28. package/dist/analysts/corrections/fix-md-fences.js +23 -23
  29. package/dist/analysts/corrections/map-reversion.js +56 -53
  30. package/dist/analysts/corrections/pruning.js +19 -16
  31. package/dist/analysts/corrections/quick-fixes/fix-any-to-proper-type.js +57 -61
  32. package/dist/analysts/corrections/quick-fixes/fix-unknown-to-specific-type.js +30 -30
  33. package/dist/analysts/corrections/reorganize-barrels.js +13 -13
  34. package/dist/analysts/corrections/rewrite-testes-aliases.js +23 -22
  35. package/dist/analysts/corrections/scoring-shared.js +19 -18
  36. package/dist/analysts/corrections/type-safety/context-analyzer.js +15 -10
  37. package/dist/analysts/corrections/type-safety/type-analyzer.js +3 -3
  38. package/dist/analysts/corrections/type-safety/type-validator.js +4 -3
  39. package/dist/analysts/corrections/type-safety/usage-analyzer.js +39 -42
  40. package/dist/analysts/css/analysts/analyst-css.js +42 -42
  41. package/dist/analysts/css/corrections/correction-css.js +19 -11
  42. package/dist/analysts/css/detectors/detector-css-best-practices.js +129 -118
  43. package/dist/analysts/css/scorers/scorer-css.js +23 -18
  44. package/dist/analysts/css-in-js/analysts/analyst-css-in-js.js +24 -17
  45. package/dist/analysts/css-in-js/corrections/correction-css-in-js.js +31 -16
  46. package/dist/analysts/css-in-js/detectors/detector-css-in-js-best-practices.js +28 -30
  47. package/dist/analysts/css-in-js/scorers/scorer-css-in-js.js +79 -54
  48. package/dist/analysts/css-in-js/shared.js +7 -0
  49. package/dist/analysts/detectors/detector-architecture.js +91 -85
  50. package/dist/analysts/detectors/detector-bugs-ml.js +29 -27
  51. package/dist/analysts/detectors/detector-code-fragile.js +41 -36
  52. package/dist/analysts/detectors/detector-dependencies.js +5 -5
  53. package/dist/analysts/detectors/detector-duplications.js +26 -26
  54. package/dist/analysts/detectors/detector-monorepo.js +51 -45
  55. package/dist/analysts/detectors/detector-performance.js +24 -17
  56. package/dist/analysts/detectors/detector-recommendation-architecture.js +40 -36
  57. package/dist/analysts/detectors/detector-security.js +43 -42
  58. package/dist/analysts/detectors/detector-structure.js +31 -28
  59. package/dist/analysts/github-actions/analysts/analyst-github-actions.js +5 -8
  60. package/dist/analysts/github-actions/detectors/detector-workflow-accessibility.js +1 -9
  61. package/dist/analysts/github-actions/detectors/detector-workflow-structure.js +1 -4
  62. package/dist/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.js +6 -5
  63. package/dist/analysts/gitlab-ci/analysts/analyst-gitlab-ci.js +2 -2
  64. package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.js +0 -3
  65. package/dist/analysts/go/analysts/analyst-best-practices.js +2 -2
  66. package/dist/analysts/go/analysts/analyst-concurrency.js +1 -1
  67. package/dist/analysts/go/analysts/analyst-security.js +1 -1
  68. package/dist/analysts/go/detectors/detector-conventions.js +1 -1
  69. package/dist/analysts/html/analysts/analyst-html.js +10 -12
  70. package/dist/analysts/html/detectors/detector-html.js +3 -3
  71. package/dist/analysts/js-ts/analysts/analyst-commands-cli.js +22 -22
  72. package/dist/analysts/js-ts/analysts/analyst-functions-long.js +5 -5
  73. package/dist/analysts/js-ts/analysts/analyst-patterns-usage.js +6 -2
  74. package/dist/analysts/js-ts/detectors/detector-anti-patterns-async.js +84 -9
  75. package/dist/analysts/js-ts/detectors/detector-constructions-syntactic.js +33 -10
  76. package/dist/analysts/js-ts/detectors/detector-context-smart.js +6 -6
  77. package/dist/analysts/js-ts/detectors/detector-leaks-memory.js +1 -1
  78. package/dist/analysts/js-ts/detectors/detector-types-unsafe.js +33 -2
  79. package/dist/analysts/php/analysts/analyst-php.js +3 -3
  80. package/dist/analysts/php/detectors/detector-php-best-practices.js +5 -5
  81. package/dist/analysts/php/detectors/detector-php-security.js +5 -5
  82. package/dist/analysts/php/scorers/scorer-php.js +2 -2
  83. package/dist/analysts/plugins/detector-documentation.js +6 -6
  84. package/dist/analysts/plugins/detector-markdown.js +7 -7
  85. package/dist/analysts/python/analysts/analyst-python.js +2 -5
  86. package/dist/analysts/react/analysts/analyst-react-hooks.js +66 -9
  87. package/dist/analysts/react/analysts/analyst-react.js +46 -2
  88. package/dist/analysts/react/corrections/correction-react.js +41 -1
  89. package/dist/analysts/react/detectors/detector-react-best-practices.js +5 -5
  90. package/dist/analysts/react/scorers/scorer-react.js +36 -1
  91. package/dist/analysts/registry/autodiscovery.js +2 -2
  92. package/dist/analysts/rust/analysts/analyst-best-practices.js +42 -3
  93. package/dist/analysts/rust/analysts/analyst-memory.js +2 -2
  94. package/dist/analysts/rust/analysts/analyst-rust.js +52 -5
  95. package/dist/analysts/rust/analysts/analyst-security.js +29 -1
  96. package/dist/analysts/scorers/scorer.js +5 -5
  97. package/dist/analysts/shell/analysts/analyst-shell.js +81 -5
  98. package/dist/analysts/shell/corrections/correction-shell.js +34 -1
  99. package/dist/analysts/shell/detectors/detector-shell-security.js +88 -0
  100. package/dist/analysts/shell/scorers/scorer-shell.js +58 -1
  101. package/dist/analysts/strategists/operator-structure.js +5 -7
  102. package/dist/analysts/strategists/suggestions-contextuais.js +5 -2
  103. package/dist/analysts/svg/analysts/analyst-svg.js +1 -0
  104. package/dist/analysts/tailwind/analysts/analyst-tailwind.js +79 -55
  105. package/dist/analysts/tailwind/corrections/correction-tailwind.js +108 -9
  106. package/dist/analysts/tailwind/detectors/detector-tailwind-best-practices.js +122 -7
  107. package/dist/analysts/tailwind/scorers/scorer-tailwind.js +62 -11
  108. package/dist/analysts/xml/analysts/analyst-xml.js +2 -2
  109. package/dist/app/index.js +1 -0
  110. package/dist/bin/cli-bootstrap.js +6 -4
  111. package/dist/bin/index.js +6 -4
  112. package/dist/caretakers/scoring.js +1 -0
  113. package/dist/cli/commands/command-analysts.js +4 -3
  114. package/dist/cli/commands/command-azure.js +1 -1
  115. package/dist/cli/commands/command-circleci.js +1 -1
  116. package/dist/cli/commands/command-compliance.js +1 -1
  117. package/dist/cli/commands/command-diagnose.js +10 -13
  118. package/dist/cli/commands/command-fix-types.js +9 -32
  119. package/dist/cli/commands/command-formatters.js +2 -2
  120. package/dist/cli/commands/command-github-actions.js +1 -1
  121. package/dist/cli/commands/command-gitlab-ci.js +1 -1
  122. package/dist/cli/commands/command-guardian.js +1 -1
  123. package/dist/cli/commands/command-imports.js +6 -6
  124. package/dist/cli/commands/command-jenkins.js +1 -1
  125. package/dist/cli/commands/command-licenses.js +1 -1
  126. package/dist/cli/commands/command-marketplace.js +7 -7
  127. package/dist/cli/commands/command-names.js +3 -8
  128. package/dist/cli/commands/command-perf.js +7 -9
  129. package/dist/cli/commands/command-plugins.js +4 -4
  130. package/dist/cli/diagnostic/auto-fix.js +2 -2
  131. package/dist/cli/diagnostic/exporters/json-exporter.js +1 -1
  132. package/dist/cli/diagnostic/exporters/sharded-exporter.js +0 -3
  133. package/dist/cli/diagnostic/exporters/svg-optimization-exporter.js +1 -1
  134. package/dist/cli/diagnostic/filters.js +9 -9
  135. package/dist/cli/diagnostic/handlers/archetype-handler.js +3 -6
  136. package/dist/cli/diagnostic/handlers/auto-fix-handler.js +4 -4
  137. package/dist/cli/diagnostic/handlers/guardian-handler.js +1 -1
  138. package/dist/cli/diagnostic/processing-diagnostic.js +31 -35
  139. package/dist/cli/diagnostic/processing-helpers.js +2 -2
  140. package/dist/cli/handlers/fix-types-exporter.js +1 -4
  141. package/dist/cli/helpers/display-frame.js +5 -5
  142. package/dist/core/config/auto/auto-fix-config.js +0 -6
  143. package/dist/core/config/chalk-safe.js +6 -6
  144. package/dist/core/config/config.js +11 -13
  145. package/dist/core/config/conventions.js +1 -1
  146. package/dist/core/config/security.js +2 -2
  147. package/dist/core/execution/analysis-cache.js +5 -8
  148. package/dist/core/execution/ast-cache.js +1 -3
  149. package/dist/core/execution/executor.js +8 -21
  150. package/dist/core/execution/inquisitor.js +24 -21
  151. package/dist/core/execution/results.js +1 -0
  152. package/dist/core/execution/scanner.js +4 -4
  153. package/dist/core/messages/en/analysts/analyst-github-actions-messages.js +1 -1
  154. package/dist/core/messages/en/analysts/analyst-patterns-usage-messages.js +1 -0
  155. package/dist/core/messages/en/analysts/analyst-shell-messages.js +15 -0
  156. package/dist/core/messages/en/analysts/detector-constructions-syntactic-messages.js +6 -0
  157. package/dist/core/messages/en/analysts/detector-js-ts-messages.js +27 -0
  158. package/dist/core/messages/en/analysts/detector-react-messages.js +8 -0
  159. package/dist/core/messages/en/analysts/detector-shell-messages.js +17 -0
  160. package/dist/core/messages/en/analysts/detector-tailwind-messages.js +3 -3
  161. package/dist/core/messages/en/analysts/report-circleci-messages.js +7 -7
  162. package/dist/core/messages/en/caretakers/caretaker-messages.js +1 -7
  163. package/dist/core/messages/en/core/plugin-messages.js +31 -3
  164. package/dist/core/messages/en/log/log.js +4 -4
  165. package/dist/core/messages/en/ui/filter-config.js +1 -5
  166. package/dist/core/messages/i18n-system.js +3 -3
  167. package/dist/core/messages/index.js +3 -3
  168. package/dist/core/messages/ja/analysts/analyst-github-actions-messages.js +1 -1
  169. package/dist/core/messages/ja/analysts/analyst-patterns-usage-messages.js +1 -0
  170. package/dist/core/messages/ja/analysts/analyst-shell-messages.js +15 -0
  171. package/dist/core/messages/ja/analysts/detector-constructions-syntactic-messages.js +6 -0
  172. package/dist/core/messages/ja/analysts/detector-js-ts-messages.js +27 -0
  173. package/dist/core/messages/ja/analysts/detector-react-messages.js +8 -0
  174. package/dist/core/messages/ja/analysts/detector-shell-messages.js +17 -0
  175. package/dist/core/messages/ja/analysts/detector-tailwind-messages.js +3 -3
  176. package/dist/core/messages/ja/analysts/report-circleci-messages.js +7 -7
  177. package/dist/core/messages/ja/caretakers/caretaker-messages.js +1 -7
  178. package/dist/core/messages/ja/core/plugin-messages.js +31 -3
  179. package/dist/core/messages/ja/log/log.js +4 -4
  180. package/dist/core/messages/ja/ui/filter-config.js +1 -1
  181. package/dist/core/messages/pt/analysts/analyst-github-actions-messages.js +1 -1
  182. package/dist/core/messages/pt/analysts/analyst-patterns-usage-messages.js +1 -0
  183. package/dist/core/messages/pt/analysts/analyst-shell-messages.js +15 -0
  184. package/dist/core/messages/pt/analysts/detector-constructions-syntactic-messages.js +6 -0
  185. package/dist/core/messages/pt/analysts/detector-js-ts-messages.js +27 -0
  186. package/dist/core/messages/pt/analysts/detector-react-messages.js +8 -0
  187. package/dist/core/messages/pt/analysts/detector-shell-messages.js +17 -0
  188. package/dist/core/messages/pt/analysts/detector-tailwind-messages.js +3 -3
  189. package/dist/core/messages/pt/analysts/report-circleci-messages.js +7 -7
  190. package/dist/core/messages/pt/caretakers/caretaker-messages.js +1 -7
  191. package/dist/core/messages/pt/core/plugin-messages.js +31 -3
  192. package/dist/core/messages/pt/log/log-engine.js +6 -6
  193. package/dist/core/messages/pt/log/log.js +3 -3
  194. package/dist/core/messages/pt/ui/filter-config.js +1 -1
  195. package/dist/core/messages/shared/icons.js +3 -3
  196. package/dist/core/messages/zh/analysts/analyst-github-actions-messages.js +1 -1
  197. package/dist/core/messages/zh/analysts/analyst-patterns-usage-messages.js +1 -0
  198. package/dist/core/messages/zh/analysts/analyst-shell-messages.js +15 -0
  199. package/dist/core/messages/zh/analysts/detector-constructions-syntactic-messages.js +6 -0
  200. package/dist/core/messages/zh/analysts/detector-js-ts-messages.js +27 -0
  201. package/dist/core/messages/zh/analysts/detector-react-messages.js +8 -0
  202. package/dist/core/messages/zh/analysts/detector-shell-messages.js +17 -0
  203. package/dist/core/messages/zh/analysts/detector-tailwind-messages.js +3 -3
  204. package/dist/core/messages/zh/analysts/report-circleci-messages.js +7 -7
  205. package/dist/core/messages/zh/caretakers/caretaker-messages.js +1 -7
  206. package/dist/core/messages/zh/core/plugin-messages.js +31 -3
  207. package/dist/core/messages/zh/log/log.js +3 -3
  208. package/dist/core/messages/zh/ui/filter-config.js +1 -5
  209. package/dist/core/parsing/filters.js +3 -3
  210. package/dist/core/parsing/langs/json.js +1 -1
  211. package/dist/core/parsing/langs/python.js +1 -1
  212. package/dist/core/parsing/langs/typescript.js +1 -1
  213. package/dist/core/parsing/parser.js +3 -4
  214. package/dist/core/parsing/utils.js +1 -0
  215. package/dist/core/registry/file-registry.js +3 -2
  216. package/dist/core/registry/paths.js +3 -3
  217. package/dist/core/reporting/default-reporter.js +2 -2
  218. package/dist/core/schema/version.js +6 -6
  219. package/dist/core/workers/worker-executor.js +3 -3
  220. package/dist/core/workers/worker-pool.js +0 -0
  221. package/dist/guardian/baseline.js +1 -1
  222. package/dist/guardian/gpg.js +3 -1
  223. package/dist/guardian/integrity.js +2 -7
  224. package/dist/guardian/records.js +7 -1
  225. package/dist/guardian/result.js +1 -1
  226. package/dist/guardian/sentinel.js +7 -1
  227. package/dist/guardian/watcher-hidden.js +6 -1
  228. package/dist/licenses/fs-utils.js +5 -1
  229. package/dist/licenses/generate-notices.js +1 -1
  230. package/dist/licenses/index.js +1 -0
  231. package/dist/licenses/normalizer.js +10 -9
  232. package/dist/node.loader.js +224 -4
  233. package/dist/reports/analise-async-patterns.js +1 -1
  234. package/dist/reports/filter-smart.js +2 -5
  235. package/dist/reports/generator-report.js +7 -7
  236. package/dist/reports/report-archetypes.js +10 -10
  237. package/dist/reports/report-caretaker-health.js +2 -1
  238. package/dist/reports/report-patterns-usage.js +1 -1
  239. package/dist/sdk/analyzer.js +1 -1
  240. package/dist/shared/data-processing/fragment-report.js +11 -11
  241. package/dist/shared/data-processing/json.js +1 -1
  242. package/dist/shared/data-processing/occurrences.js +3 -2
  243. package/dist/shared/formatters/code-min-formatter.js +1 -1
  244. package/dist/shared/formatters/engines/prettier.js +1 -1
  245. package/dist/shared/formatters/engines/stylelint.js +43 -40
  246. package/dist/shared/formatters/formatter.js +8 -8
  247. package/dist/shared/formatters/formatters/code.js +3 -3
  248. package/dist/shared/formatters/formatters/css.js +2 -10
  249. package/dist/shared/formatters/formatters/dotfiles.js +1 -1
  250. package/dist/shared/formatters/formatters/html.js +1 -5
  251. package/dist/shared/formatters/formatters/json.js +0 -3
  252. package/dist/shared/formatters/formatters/markdown.js +19 -24
  253. package/dist/shared/formatters/formatters/properties.js +2 -2
  254. package/dist/shared/formatters/formatters/shell.js +1 -4
  255. package/dist/shared/formatters/formatters/sql.js +0 -3
  256. package/dist/shared/formatters/formatters/xml.js +5 -7
  257. package/dist/shared/formatters/formatters/yaml.js +2 -7
  258. package/dist/shared/formatters/index.js +1 -1
  259. package/dist/shared/helpers/framework-detector.js +6 -2
  260. package/dist/shared/helpers/json.js +1 -1
  261. package/dist/shared/helpers/magic-constants-whitelist.js +1 -1
  262. package/dist/shared/helpers/masking.js +17 -17
  263. package/dist/shared/helpers/reader-report.js +0 -12
  264. package/dist/shared/helpers/structural-hash.js +3 -2
  265. package/dist/shared/helpers/structure.js +1 -1
  266. package/dist/shared/marketplace/registry.js +1 -1
  267. package/dist/shared/marketplace/remote.js +4 -4
  268. package/dist/shared/persistence/persistence.js +13 -6
  269. package/dist/shared/plugins/core-plugin.js +5 -1
  270. package/dist/shared/plugins/registry.js +3 -2
  271. package/dist/types/analysts/tailwind-correction.js +2 -0
  272. package/dist/types/caretakers/imports-barrel.js +1 -0
  273. package/dist/types/caretakers/index.js +4 -0
  274. package/dist/types/caretakers/map-reversion.js +1 -0
  275. package/dist/types/caretakers/pruning.js +1 -0
  276. package/dist/types/caretakers/scoring.js +1 -0
  277. package/dist/types/common/analysts.js +1 -1
  278. package/dist/types/core/config/filters.js +1 -0
  279. package/dist/types/core/config/index.js +2 -0
  280. package/dist/types/core/execution/ambiente.js +1 -0
  281. package/dist/types/core/execution/linguagens.js +1 -0
  282. package/dist/types/core/execution/parse-errors.js +1 -0
  283. package/dist/types/core/execution/results.js +1 -0
  284. package/dist/types/core/execution/structure-json.js +1 -0
  285. package/dist/types/core/index.js +1 -0
  286. package/dist/types/core/messages/index.js +1 -0
  287. package/dist/types/core/messages/log.js +1 -0
  288. package/dist/types/core/parsing/babel-narrow.js +1 -0
  289. package/dist/types/core/parsing/index.js +1 -0
  290. package/dist/types/core/runtime.js +1 -0
  291. package/dist/types/guardian/index.js +2 -0
  292. package/dist/types/guardian/integrity.js +7 -0
  293. package/dist/types/guardian/snapshot.js +1 -0
  294. package/dist/types/index.js +4 -4
  295. package/dist/types/licenses/index.js +2 -0
  296. package/dist/types/processing/display.js +16 -13
  297. package/dist/types/processing/filters.js +8 -11
  298. package/dist/types/reports/compliance.js +1 -0
  299. package/dist/types/reports/streaming.js +1 -0
  300. package/dist/types/scripts/index.js +1 -0
  301. package/dist/types/scripts/migrar-aliases.js +1 -0
  302. package/dist/types/sdk/index.js +1 -0
  303. package/dist/types/shared/index.js +2 -0
  304. package/dist/types/vulnerabilities/index.js +2 -0
  305. package/dist/vulnerabilities/scanner.js +3 -2
  306. package/package.json +14 -20
@@ -34,35 +34,33 @@ function collectCssIssues(src, relPath) {
34
34
  });
35
35
  }
36
36
  const current = stack[stack.length - 1];
37
- if (current) {
38
- const propMatch = /^([a-zA-Z-]+)\s*:\s*([^;]+)?/.exec(trimmed);
39
- if (propMatch) {
40
- const prop = propMatch[1].toLowerCase();
41
- const value = (propMatch[2] || '').trim();
42
- const prev = current.props[prop];
43
- if (prev) {
44
- const ctx = current.context ? {
45
- currentAtRule: current.context
46
- } : undefined;
47
- if (isLikelyIntentionalDuplicate(prop, prev.value, value, ctx)) {
48
- // Duplicata legítima (fallback vendor, viewport, cor, etc)
49
- }
50
- else if (prev.value === value) {
51
- // Mesma propriedade, mesmo valor = erro claro
52
- ocorrencias.push(warn(messages.CssMensagens.duplicatePropertySame(prop), relPath, line));
53
- }
54
- else {
55
- // Valores diferentes sem padrão claro = possível erro
56
- ocorrencias.push(warn(messages.CssMensagens.duplicatePropertyDifferent(prop, prev.value, value), relPath, line));
57
- }
37
+ const propMatch = /^([a-zA-Z-]+)\s*:\s*([^;]+)?/.exec(trimmed);
38
+ if (propMatch) {
39
+ const prop = propMatch[1].toLowerCase();
40
+ const value = (propMatch[2] || '').trim();
41
+ const prev = current.props[prop];
42
+ if (prop in current.props) {
43
+ const ctx = {
44
+ currentAtRule: current.context
45
+ };
46
+ if (isLikelyIntentionalDuplicate(prop, prev.value, value, ctx)) {
47
+ // Duplicata legítima (fallback vendor, viewport, cor, etc)
48
+ }
49
+ else if (prev.value === value) {
50
+ // Mesma propriedade, mesmo valor = erro claro
51
+ ocorrencias.push(warn(messages.CssMensagens.duplicatePropertySame(prop), relPath, line));
58
52
  }
59
53
  else {
60
- current.props[prop] = {
61
- line,
62
- value
63
- };
54
+ // Valores diferentes sem padrão claro = possível erro
55
+ ocorrencias.push(warn(messages.CssMensagens.duplicatePropertyDifferent(prop, prev.value, value), relPath, line));
64
56
  }
65
57
  }
58
+ else {
59
+ current.props[prop] = {
60
+ line,
61
+ value
62
+ };
63
+ }
66
64
  }
67
65
  // !important
68
66
  if (/!important/.test(trimmed)) {
@@ -125,7 +123,8 @@ function splitSimpleSelectors(selectorText) {
125
123
  function parseWithPostCssRoots(src, relPath) {
126
124
  const isScss = /\.scss$/i.test(relPath);
127
125
  const isSass = /\.sass$/i.test(relPath);
128
- const syntax = isScss ? postcssScss : isSass ? postcssSass : undefined;
126
+ const rawSyntax = isScss ? postcssScss : isSass ? postcssSass : undefined;
127
+ const syntax = rawSyntax;
129
128
  try {
130
129
  // Importante: `postcss.parse(..., { syntax })` ignora `syntax`.
131
130
  // Para aplicar parser SCSS/SASS corretamente, usamos `postcss().process`.
@@ -214,6 +213,18 @@ function detectCssHacks(value) {
214
213
  }
215
214
  return null;
216
215
  }
216
+ function processDuplicateProperty(propChave, propRaw, prev, value, inFontFace, relPath, line, pushOnce) {
217
+ const ctx = inFontFace ? { currentAtRule: 'font-face' } : undefined;
218
+ if (isLikelyIntentionalDuplicate(propChave, prev.value, value, ctx)) {
219
+ return;
220
+ }
221
+ if (prev.value === value) {
222
+ pushOnce(warn(messages.CssMensagens.duplicatePropertySame(propRaw), relPath, line));
223
+ }
224
+ else {
225
+ pushOnce(warn(messages.CssMensagens.duplicatePropertyDifferent(propRaw, prev.value, value), relPath, line));
226
+ }
227
+ }
217
228
  function collectCssIssuesFromPostCssAst(root, relPath) {
218
229
  const ocorrencias = [];
219
230
  const seen = new Set();
@@ -242,19 +253,8 @@ function collectCssIssuesFromPostCssAst(root, relPath) {
242
253
  const value = normalizeCssValue(`${(decl.value || '')}${decl.important ? ' !important' : ''}`);
243
254
  const line = getNodeLine(decl);
244
255
  const prev = props[propChave];
245
- if (prev) {
246
- const ctx = inFontFace ? {
247
- currentAtRule: 'font-face'
248
- } : undefined;
249
- if (isLikelyIntentionalDuplicate(propChave, prev.value, value, ctx)) {
250
- // duplicata intencional
251
- }
252
- else if (prev.value === value) {
253
- pushOnce(warn(messages.CssMensagens.duplicatePropertySame(propRaw), relPath, line));
254
- }
255
- else {
256
- pushOnce(warn(messages.CssMensagens.duplicatePropertyDifferent(propRaw, prev.value, value), relPath, line));
257
- }
256
+ if (propChave in props) {
257
+ processDuplicateProperty(propChave, propRaw, prev, value, inFontFace, relPath, line, pushOnce);
258
258
  }
259
259
  props[propChave] = {
260
260
  value,
@@ -280,11 +280,11 @@ function collectCssIssuesFromPostCssAst(root, relPath) {
280
280
  // 2) Unificação/centralização (apenas em regras com seletores simples)
281
281
  if (container.type === 'rule') {
282
282
  const rule = container;
283
- const selectorText = (rule.selector || '');
283
+ const selectorText = rule.selector;
284
284
  const simpleSelectors = splitSimpleSelectors(selectorText);
285
285
  if (simpleSelectors.length) {
286
286
  const decls = [];
287
- rule.nodes.forEach(node => {
287
+ rule.nodes?.forEach(node => {
288
288
  if (node.type !== 'decl') {
289
289
  return;
290
290
  }
@@ -300,7 +300,7 @@ function collectCssIssuesFromPostCssAst(root, relPath) {
300
300
  });
301
301
  });
302
302
  // Detecta regras vazias (ignora @apply do Tailwind CSS)
303
- const hasApplyDirective = rule.nodes.some(node => node.type === 'atrule' && (node).name === 'apply') ?? false;
303
+ const hasApplyDirective = rule.nodes?.some(node => node.type === 'atrule' && (node).name === 'apply');
304
304
  if (decls.length === 0 && !hasApplyDirective) {
305
305
  pushOnce(warn(messages.CssMensagens.emptyRule, relPath, getNodeLine(rule)));
306
306
  }
@@ -10,6 +10,22 @@
10
10
  import { messages } from '../../../core/messages/index.js';
11
11
  import { splitLines } from '../../../shared/helpers/index.js';
12
12
  import { criarOcorrencia } from '../../../types/index.js';
13
+ function detectarIdSelector(linha, numeroLinha) {
14
+ if (!/#[a-zA-Z0-9_-]+\s*\{/.test(linha)) {
15
+ return null;
16
+ }
17
+ const idMatch = linha.match(/#([a-zA-Z0-9_-]+)/);
18
+ if (!idMatch) {
19
+ return null;
20
+ }
21
+ return {
22
+ tipo: 'css-id-to-class',
23
+ original: linha.trim(),
24
+ sugerido: linha.replace(/#([a-zA-Z0-9_-]+)/, `.${idMatch[1]}`),
25
+ linha: numeroLinha,
26
+ confianca: 70
27
+ };
28
+ }
13
29
  export function detectarCorrecoesCss(src, _relPath) {
14
30
  const correcoes = [];
15
31
  const linhas = splitLines(src);
@@ -24,17 +40,9 @@ export function detectarCorrecoesCss(src, _relPath) {
24
40
  confianca: 80
25
41
  });
26
42
  }
27
- if (/#[a-zA-Z0-9_-]+\s*\{/.test(linha)) {
28
- const idMatch = linha.match(/#([a-zA-Z0-9_-]+)/);
29
- if (idMatch) {
30
- correcoes.push({
31
- tipo: 'css-id-to-class',
32
- original: linha.trim(),
33
- sugerido: linha.replace(/#([a-zA-Z0-9_-]+)/, `.${idMatch[1]}`),
34
- linha: numeroLinha,
35
- confianca: 70
36
- });
37
- }
43
+ const idCorrection = detectarIdSelector(linha, numeroLinha);
44
+ if (idCorrection) {
45
+ correcoes.push(idCorrection);
38
46
  }
39
47
  });
40
48
  return correcoes;
@@ -63,151 +63,162 @@ export const detectorCssBestPractices = {
63
63
  const _idSelectorCount = 0;
64
64
  const allSelectors = [];
65
65
  const _selectorDepth = 0;
66
- linhas.forEach((linha, index) => {
67
- const numeroLinha = index + 1;
68
- const trimmed = linha.trim();
69
- if (trimmed.includes('{')) {
70
- depth++;
71
- if (depth > maxDepth) {
72
- maxDepth = depth;
66
+ function processarAberturaBloco(linha, trimmed, numeroLinha) {
67
+ depth++;
68
+ if (depth > maxDepth) {
69
+ maxDepth = depth;
70
+ }
71
+ const selectorPart = trimmed.replace(/\s*\{.*$/, '').trim();
72
+ if (!selectorPart) {
73
+ return;
74
+ }
75
+ allSelectors.push(selectorPart);
76
+ const simpleCount = selectorPart.split(',').length;
77
+ if (simpleCount > 5) {
78
+ ocorrencias.push(criarOcorrencia({
79
+ tipo: 'css-too-many-selectors',
80
+ nivel: 'info',
81
+ mensagem: messages.DetectorCssMensagens.tooManySelectors,
82
+ relPath,
83
+ linha: numeroLinha,
84
+ sugestao: messages.DetectorCssMensagens.tooManySelectorsSugestao
85
+ }));
86
+ }
87
+ const baseSelector = selectorPart.replace(/,.*$/, '').trim();
88
+ if (baseSelector) {
89
+ if (seenSelectors.has(baseSelector)) {
90
+ seenSelectors.get(baseSelector)?.push(numeroLinha);
73
91
  }
74
- const selectorPart = trimmed.replace(/\s*\{.*$/, '').trim();
75
- if (selectorPart) {
76
- allSelectors.push(selectorPart);
77
- const simpleCount = selectorPart.split(',').length;
78
- if (simpleCount > 5) {
79
- ocorrencias.push(criarOcorrencia({
80
- tipo: 'css-too-many-selectors',
81
- nivel: 'info',
82
- mensagem: messages.DetectorCssMensagens.tooManySelectors,
83
- relPath,
84
- linha: numeroLinha,
85
- sugestao: messages.DetectorCssMensagens.tooManySelectorsSugestao
86
- }));
87
- }
88
- const baseSelector = selectorPart.replace(/,.*$/, '').trim();
89
- if (baseSelector) {
90
- if (seenSelectors.has(baseSelector)) {
91
- seenSelectors.get(baseSelector)?.push(numeroLinha);
92
- }
93
- else {
94
- seenSelectors.set(baseSelector, [numeroLinha]);
95
- }
96
- }
92
+ else {
93
+ seenSelectors.set(baseSelector, [numeroLinha]);
97
94
  }
98
95
  }
99
- if (trimmed.includes('}')) {
100
- if (propsInBlock.size === 0 && depth > 0) {
101
- ocorrencias.push(criarOcorrencia({
102
- tipo: 'css-empty-rule',
103
- nivel: 'info',
104
- mensagem: messages.DetectorCssMensagens.emptyRule,
105
- relPath,
106
- linha: numeroLinha,
107
- sugestao: messages.DetectorCssMensagens.emptyRuleSugestao
108
- }));
109
- }
110
- propsInBlock.clear();
111
- depth--;
96
+ }
97
+ function processarFechamentoBloco(numeroLinha) {
98
+ if (propsInBlock.size === 0 && depth > 0) {
99
+ ocorrencias.push(criarOcorrencia({
100
+ tipo: 'css-empty-rule',
101
+ nivel: 'info',
102
+ mensagem: messages.DetectorCssMensagens.emptyRule,
103
+ relPath,
104
+ linha: numeroLinha,
105
+ sugestao: messages.DetectorCssMensagens.emptyRuleSugestao
106
+ }));
112
107
  }
113
- if (/!important/.test(trimmed)) {
108
+ propsInBlock.clear();
109
+ depth--;
110
+ }
111
+ function processarPropriedade(trimmed, numeroLinha) {
112
+ const propMatch = /^([a-zA-Z-]+)\s*:\s*([^;]+)?/.exec(trimmed);
113
+ if (!propMatch || depth <= 0) {
114
+ return;
115
+ }
116
+ const prop = propMatch[1].toLowerCase();
117
+ const value = (propMatch[2] || '').trim();
118
+ allDeclaredProps.push(prop);
119
+ if (propsInBlock.has(prop)) {
114
120
  ocorrencias.push(criarOcorrencia({
115
- tipo: 'css-important-usage',
121
+ tipo: 'css-duplicate-property',
116
122
  nivel: 'aviso',
117
- mensagem: messages.DetectorCssMensagens.important,
123
+ mensagem: messages.DetectorCssMensagens.duplicateProperty(prop),
118
124
  relPath,
119
125
  linha: numeroLinha,
120
- sugestao: messages.DetectorCssMensagens.importantSugestao
126
+ sugestao: messages.DetectorCssMensagens.duplicatePropertySugestao
121
127
  }));
122
128
  }
123
- const propMatch = /^([a-zA-Z-]+)\s*:\s*([^;]+)?/.exec(trimmed);
124
- if (propMatch && depth > 0) {
125
- const prop = propMatch[1].toLowerCase();
126
- const value = (propMatch[2] || '').trim();
127
- allDeclaredProps.push(prop);
128
- if (propsInBlock.has(prop)) {
129
- ocorrencias.push(criarOcorrencia({
130
- tipo: 'css-duplicate-property',
131
- nivel: 'aviso',
132
- mensagem: messages.DetectorCssMensagens.duplicateProperty(prop),
133
- relPath,
134
- linha: numeroLinha,
135
- sugestao: messages.DetectorCssMensagens.duplicatePropertySugestao
136
- }));
137
- }
138
- propsInBlock.set(prop, { line: numeroLinha, value });
139
- if (value === '0' && !prop.startsWith('--')) {
129
+ propsInBlock.set(prop, { line: numeroLinha, value });
130
+ if (value === '0' && !prop.startsWith('--')) {
131
+ ocorrencias.push(criarOcorrencia({
132
+ tipo: 'css-unitless-zero',
133
+ nivel: 'info',
134
+ mensagem: messages.DetectorCssMensagens.unitlessZero,
135
+ relPath,
136
+ linha: numeroLinha,
137
+ sugestao: messages.DetectorCssMensagens.unitlessZeroSugestao
138
+ }));
139
+ }
140
+ if (prop === 'font-family') {
141
+ const families = value.split(',').map(f => f.trim().replace(/['"]/g, ''));
142
+ const hasGeneric = families.some(f => GENERIC_FONTS.has(f.toLowerCase()));
143
+ if (!hasGeneric) {
140
144
  ocorrencias.push(criarOcorrencia({
141
- tipo: 'css-unitless-zero',
145
+ tipo: 'css-font-stack-missing',
142
146
  nivel: 'info',
143
- mensagem: messages.DetectorCssMensagens.unitlessZero,
147
+ mensagem: messages.DetectorCssMensagens.fontStackMissing,
144
148
  relPath,
145
149
  linha: numeroLinha,
146
- sugestao: messages.DetectorCssMensagens.unitlessZeroSugestao
150
+ sugestao: messages.DetectorCssMensagens.fontStackMissingSugestao
147
151
  }));
148
152
  }
149
- if (prop === 'font-family') {
150
- const families = value.split(',').map(f => f.trim().replace(/['"]/g, ''));
151
- const hasGeneric = families.some(f => GENERIC_FONTS.has(f.toLowerCase()));
152
- if (!hasGeneric) {
153
- ocorrencias.push(criarOcorrencia({
154
- tipo: 'css-font-stack-missing',
155
- nivel: 'info',
156
- mensagem: messages.DetectorCssMensagens.fontStackMissing,
157
- relPath,
158
- linha: numeroLinha,
159
- sugestao: messages.DetectorCssMensagens.fontStackMissingSugestao
160
- }));
161
- }
162
- }
163
- if (prop === 'z-index') {
164
- const zVal = parseInt(value, 10);
165
- if (!isNaN(zVal) && (zVal > 100 || zVal < -1)) {
166
- ocorrencias.push(criarOcorrencia({
167
- tipo: 'css-zindex-unmanaged',
168
- nivel: 'aviso',
169
- mensagem: messages.DetectorCssMensagens.zIndexUnmanaged,
170
- relPath,
171
- linha: numeroLinha,
172
- sugestao: messages.DetectorCssMensagens.zIndexUnmanagedSugestao
173
- }));
174
- }
175
- }
176
- if (/^(px|pt|pc|mm|cm|in)\b/.test(value) && (prop.startsWith('width') || prop.startsWith('height') || prop === 'font-size')) {
153
+ }
154
+ if (prop === 'z-index') {
155
+ const zVal = parseInt(value, 10);
156
+ if (!isNaN(zVal) && (zVal > 100 || zVal < -1)) {
177
157
  ocorrencias.push(criarOcorrencia({
178
- tipo: 'css-absolute-units',
179
- nivel: 'info',
180
- mensagem: messages.DetectorCssMensagens.absoluteUnits,
158
+ tipo: 'css-zindex-unmanaged',
159
+ nivel: 'aviso',
160
+ mensagem: messages.DetectorCssMensagens.zIndexUnmanaged,
181
161
  relPath,
182
162
  linha: numeroLinha,
183
- sugestao: messages.DetectorCssMensagens.absoluteUnitsSugestao
163
+ sugestao: messages.DetectorCssMensagens.zIndexUnmanagedSugestao
184
164
  }));
185
165
  }
186
- const missingPrefix = detectMissingVendorPrefix(prop);
187
- if (missingPrefix) {
166
+ }
167
+ if (/^(px|pt|pc|mm|cm|in)\b/.test(value) && (prop.startsWith('width') || prop.startsWith('height') || prop === 'font-size')) {
168
+ ocorrencias.push(criarOcorrencia({
169
+ tipo: 'css-absolute-units',
170
+ nivel: 'info',
171
+ mensagem: messages.DetectorCssMensagens.absoluteUnits,
172
+ relPath,
173
+ linha: numeroLinha,
174
+ sugestao: messages.DetectorCssMensagens.absoluteUnitsSugestao
175
+ }));
176
+ }
177
+ const missingPrefix = detectMissingVendorPrefix(prop);
178
+ if (missingPrefix) {
179
+ ocorrencias.push(criarOcorrencia({
180
+ tipo: 'css-vendor-prefix-missing',
181
+ nivel: 'aviso',
182
+ mensagem: messages.DetectorCssMensagens.vendorPrefixMissing,
183
+ relPath,
184
+ linha: numeroLinha,
185
+ sugestao: messages.DetectorCssMensagens.vendorPrefixMissingSugestao
186
+ }));
187
+ }
188
+ if (CSS_SHORTHAND_PROPS.has(prop)) {
189
+ const related = allDeclaredProps.filter(p => p.startsWith(`${prop}-`));
190
+ if (related.length >= 2) {
188
191
  ocorrencias.push(criarOcorrencia({
189
- tipo: 'css-vendor-prefix-missing',
190
- nivel: 'aviso',
191
- mensagem: messages.DetectorCssMensagens.vendorPrefixMissing,
192
+ tipo: 'css-missing-shorthand',
193
+ nivel: 'info',
194
+ mensagem: messages.DetectorCssMensagens.missingShorthand,
192
195
  relPath,
193
196
  linha: numeroLinha,
194
- sugestao: messages.DetectorCssMensagens.vendorPrefixMissingSugestao
197
+ sugestao: messages.DetectorCssMensagens.missingShorthandSugestao
195
198
  }));
196
199
  }
197
- if (CSS_SHORTHAND_PROPS.has(prop)) {
198
- const related = allDeclaredProps.filter(p => p.startsWith(`${prop}-`));
199
- if (related.length >= 2) {
200
- ocorrencias.push(criarOcorrencia({
201
- tipo: 'css-missing-shorthand',
202
- nivel: 'info',
203
- mensagem: messages.DetectorCssMensagens.missingShorthand,
204
- relPath,
205
- linha: numeroLinha,
206
- sugestao: messages.DetectorCssMensagens.missingShorthandSugestao
207
- }));
208
- }
209
- }
210
200
  }
201
+ }
202
+ linhas.forEach((linha, index) => {
203
+ const numeroLinha = index + 1;
204
+ const trimmed = linha.trim();
205
+ if (trimmed.includes('{')) {
206
+ processarAberturaBloco(linha, trimmed, numeroLinha);
207
+ }
208
+ if (trimmed.includes('}')) {
209
+ processarFechamentoBloco(numeroLinha);
210
+ }
211
+ if (/!important/.test(trimmed)) {
212
+ ocorrencias.push(criarOcorrencia({
213
+ tipo: 'css-important-usage',
214
+ nivel: 'aviso',
215
+ mensagem: messages.DetectorCssMensagens.important,
216
+ relPath,
217
+ linha: numeroLinha,
218
+ sugestao: messages.DetectorCssMensagens.importantSugestao
219
+ }));
220
+ }
221
+ processarPropriedade(trimmed, numeroLinha);
211
222
  if (/#[a-zA-Z0-9_-]+\s*\{/.test(trimmed)) {
212
223
  ocorrencias.push(criarOcorrencia({
213
224
  tipo: 'css-id-selector',
@@ -1,5 +1,27 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  import { splitLines } from '../../../shared/helpers/index.js';
3
+ function contarPropriedadesPorBloco(linhas) {
4
+ const props = new Map();
5
+ let inBlock = false;
6
+ for (const linha of linhas) {
7
+ if (linha.includes('{')) {
8
+ inBlock = true;
9
+ props.clear();
10
+ }
11
+ if (linha.includes('}')) {
12
+ inBlock = false;
13
+ continue;
14
+ }
15
+ if (inBlock) {
16
+ const match = /^\s*([a-zA-Z-]+)\s*:/.exec(linha);
17
+ if (match) {
18
+ const prop = match[1].toLowerCase();
19
+ props.set(prop, (props.get(prop) ?? 0) + 1);
20
+ }
21
+ }
22
+ }
23
+ return props;
24
+ }
3
25
  export function pontuarCss(src, _relPath) {
4
26
  let score = 0;
5
27
  const maxScore = 100;
@@ -20,24 +42,7 @@ export function pontuarCss(src, _relPath) {
20
42
  score += 3;
21
43
  issues.push(`${importantCount} usos de !important - refatore especificidade`);
22
44
  }
23
- const props = new Map();
24
- let inBlock = false;
25
- linhas.forEach(linha => {
26
- if (linha.includes('{')) {
27
- inBlock = true;
28
- props.clear();
29
- }
30
- if (linha.includes('}')) {
31
- inBlock = false;
32
- }
33
- if (inBlock) {
34
- const match = /^\s*([a-zA-Z-]+)\s*:/.exec(linha);
35
- if (match) {
36
- const prop = match[1].toLowerCase();
37
- props.set(prop, (props.get(prop) ?? 0) + 1);
38
- }
39
- }
40
- });
45
+ const props = contarPropriedadesPorBloco(linhas);
41
46
  const duplicates = [...props.values()].filter(valor => valor > 1).length;
42
47
  if (duplicates === 0) {
43
48
  score += 10;
@@ -1,5 +1,6 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  import { messages } from '../../../core/messages/index.js';
3
+ import { IMPORTANT_PATTERN } from '../shared.js';
3
4
  import { criarAnalista, criarOcorrencia } from '../../../types/index.js';
4
5
  const disableEnv = process.env.SUKUNA_DISABLE_PLUGIN_CSS_IN_JS === '1';
5
6
  function findLine(src, index = 0) {
@@ -80,6 +81,26 @@ function detectarStyledJsx(src) {
80
81
  indices
81
82
  };
82
83
  }
84
+ function processarStyledComponents(sc, src, relPath, ocorrencias) {
85
+ if (!sc.detected) {
86
+ return;
87
+ }
88
+ const first = sc.indices[0] ?? 0;
89
+ ocorrencias.push(emitir(messages.CssInJsMensagens.detectedStyledComponents, relPath, messages.SeverityNiveis.info, findLine(src, first)));
90
+ if (sc.global) {
91
+ ocorrencias.push(emitir(messages.CssInJsMensagens.globalStyles('styled-components'), relPath, messages.SeverityNiveis.warning, findLine(src, first)));
92
+ }
93
+ }
94
+ function processarStyledJsx(sj, src, relPath, ocorrencias) {
95
+ if (!sj.detected) {
96
+ return;
97
+ }
98
+ const first = sj.indices[0] ?? 0;
99
+ ocorrencias.push(emitir(messages.CssInJsMensagens.detectedStyledJsx, relPath, messages.SeverityNiveis.info, findLine(src, first)));
100
+ if (sj.global) {
101
+ ocorrencias.push(emitir(messages.CssInJsMensagens.globalStyles('styled-jsx'), relPath, messages.SeverityNiveis.warning, findLine(src, first)));
102
+ }
103
+ }
83
104
  export const analistaCssInJs = criarAnalista({
84
105
  nome: 'analista-css-in-js',
85
106
  categoria: 'estilo',
@@ -93,7 +114,6 @@ export const analistaCssInJs = criarAnalista({
93
114
  if (relPath.includes('src/analistas/css-in-js/')) {
94
115
  return null;
95
116
  }
96
- // Prefiltro barato para evitar múltiplos matchAll em arquivos que não têm sinais.
97
117
  if (!/styled-components|styled-jsx|<style\b[^>]*\bjsx\b|\bcreateGlobalStyle\b|\bstyled\b/i.test(src)) {
98
118
  return null;
99
119
  }
@@ -103,22 +123,9 @@ export const analistaCssInJs = criarAnalista({
103
123
  if (!sc.detected && !sj.detected) {
104
124
  return null;
105
125
  }
106
- if (sc.detected) {
107
- const first = sc.indices[0] ?? 0;
108
- ocorrencias.push(emitir(messages.CssInJsMensagens.detectedStyledComponents, relPath, messages.SeverityNiveis.info, findLine(src, first)));
109
- if (sc.global) {
110
- ocorrencias.push(emitir(messages.CssInJsMensagens.globalStyles('styled-components'), relPath, messages.SeverityNiveis.warning, findLine(src, first)));
111
- }
112
- }
113
- if (sj.detected) {
114
- const first = sj.indices[0] ?? 0;
115
- ocorrencias.push(emitir(messages.CssInJsMensagens.detectedStyledJsx, relPath, messages.SeverityNiveis.info, findLine(src, first)));
116
- if (sj.global) {
117
- ocorrencias.push(emitir(messages.CssInJsMensagens.globalStyles('styled-jsx'), relPath, messages.SeverityNiveis.warning, findLine(src, first)));
118
- }
119
- }
120
- // Sinais comuns dentro de CSS em template strings / style tags
121
- if (/!important/.test(src)) {
126
+ processarStyledComponents(sc, src, relPath, ocorrencias);
127
+ processarStyledJsx(sj, src, relPath, ocorrencias);
128
+ if (IMPORTANT_PATTERN.test(src)) {
122
129
  ocorrencias.push(emitir(messages.CssInJsMensagens.importantUsage, relPath, messages.SeverityNiveis.warning, 1));
123
130
  }
124
131
  if (/url\(\s*['"]?http:\/\//i.test(src)) {
@@ -12,30 +12,45 @@
12
12
  */
13
13
  import { getMessages } from '../../../core/messages/index.js';
14
14
  import { splitLines } from '../../../shared/helpers/index.js';
15
+ import { IMPORTANT_PATTERN, IMPORTANT_WS_GLOBAL } from '../shared.js';
15
16
  import { criarOcorrencia } from '../../../types/index.js';
17
+ function detectarCreateGlobalStyle(linha, numeroLinha, m) {
18
+ if (!/createGlobalStyle/.test(linha)) {
19
+ return null;
20
+ }
21
+ return {
22
+ tipo: 'css-in-js-extract-global',
23
+ original: linha.trim(),
24
+ sugerido: m.extractGlobalCss,
25
+ linha: numeroLinha,
26
+ confianca: 70
27
+ };
28
+ }
29
+ function detectarImportantCorrection(linha, numeroLinha) {
30
+ if (!IMPORTANT_PATTERN.test(linha) || !/styled|css\s*`/.test(linha)) {
31
+ return null;
32
+ }
33
+ return {
34
+ tipo: 'css-in-js-remove-important',
35
+ original: linha.trim(),
36
+ sugerido: linha.replace(IMPORTANT_WS_GLOBAL, ''),
37
+ linha: numeroLinha,
38
+ confianca: 80
39
+ };
40
+ }
16
41
  export function detectarCorrecoesCssInJs(src, _relPath) {
17
42
  const m = getMessages().CssInJsCorrecaoMensagens;
18
43
  const correcoes = [];
19
44
  const linhas = splitLines(src);
20
45
  linhas.forEach((linha, index) => {
21
46
  const numeroLinha = index + 1;
22
- if (/createGlobalStyle/.test(linha)) {
23
- correcoes.push({
24
- tipo: 'css-in-js-extract-global',
25
- original: linha.trim(),
26
- sugerido: m.extractGlobalCss,
27
- linha: numeroLinha,
28
- confianca: 70
29
- });
47
+ const globalCorrection = detectarCreateGlobalStyle(linha, numeroLinha, m);
48
+ if (globalCorrection) {
49
+ correcoes.push(globalCorrection);
30
50
  }
31
- if (/!important/.test(linha) && /styled|css\s*`/.test(linha)) {
32
- correcoes.push({
33
- tipo: 'css-in-js-remove-important',
34
- original: linha.trim(),
35
- sugerido: linha.replace(/\s*!important/g, ''),
36
- linha: numeroLinha,
37
- confianca: 80
38
- });
51
+ const importantCorrection = detectarImportantCorrection(linha, numeroLinha);
52
+ if (importantCorrection) {
53
+ correcoes.push(importantCorrection);
39
54
  }
40
55
  });
41
56
  return correcoes;