@diegovelasquezweb/a11y-engine 0.11.50 → 0.11.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diegovelasquezweb/a11y-engine",
3
- "version": "0.11.50",
3
+ "version": "0.11.51",
4
4
  "description": "WCAG 2.2 accessibility audit engine — scanner, analyzer, and report builders",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -5,7 +5,7 @@ import { ASSETS } from "../core/asset-loader.mjs";
5
5
  const ANTHROPIC_API = "https://api.anthropic.com/v1/messages";
6
6
  const DEFAULT_MODEL = "claude-haiku-4-5-20251001";
7
7
  const MAX_CANDIDATE_FILES = 12;
8
- const SUPPORTED_EXTENSIONS = new Set([".html", ".htm", ".jsx", ".tsx", ".vue", ".astro", ".liquid"]);
8
+ const SUPPORTED_EXTENSIONS = new Set([".html", ".htm", ".jsx", ".tsx", ".vue", ".astro", ".liquid", ".css", ".scss", ".sass"]);
9
9
 
10
10
  export const FIX_ERROR_CODES = {
11
11
  INVALID_INPUT: "invalid-input",
@@ -277,12 +277,16 @@ function getCandidateFiles(projectDir, finding) {
277
277
  return allFiles.slice(0, MAX_CANDIDATE_FILES).map((f) => ({ ...f, score: 1 }));
278
278
  }
279
279
 
280
+ const styleFiles = allFiles.filter((f) => /\.(css|scss|sass)$/.test(f.rel));
281
+
280
282
  const ranked = allFiles
283
+ .filter((f) => !/\.(css|scss|sass)$/.test(f.rel))
281
284
  .map((f) => ({ ...f, score: scoreFile(f.rel, f.content, tokens) }))
282
285
  .filter((item) => item.score > 0)
283
286
  .sort((a, b) => b.score - a.score)
284
- .slice(0, MAX_CANDIDATE_FILES);
285
- return ranked;
287
+ .slice(0, MAX_CANDIDATE_FILES - styleFiles.length);
288
+
289
+ return [...ranked, ...styleFiles.map((f) => ({ ...f, score: 1 }))];
286
290
  }
287
291
 
288
292
  function buildExecution(ruleId, intelligenceRule, finding) {
@@ -326,11 +330,14 @@ function groupFindingsByFile(domFindings, projectDir) {
326
330
  ? layoutCandidates
327
331
  : allFiles.slice(0, MAX_CANDIDATE_FILES).map((f) => ({ ...f, score: 1 }));
328
332
  } else {
329
- ranked = allFiles
333
+ const styleFiles = allFiles.filter((f) => /\.(css|scss|sass)$/.test(f.rel));
334
+ const nonStyle = allFiles
335
+ .filter((f) => !/\.(css|scss|sass)$/.test(f.rel))
330
336
  .map((f) => ({ ...f, score: scoreFile(f.rel, f.content, tokens) }))
331
337
  .filter((f) => f.score > 0)
332
338
  .sort((a, b) => b.score - a.score)
333
- .slice(0, MAX_CANDIDATE_FILES);
339
+ .slice(0, MAX_CANDIDATE_FILES - styleFiles.length);
340
+ ranked = [...nonStyle, ...styleFiles.map((f) => ({ ...f, score: 1 }))];
334
341
  }
335
342
 
336
343
  const key = ranked.length > 0 ? ranked[0].rel : `__no_candidates_${finding.id}`;
@@ -449,8 +456,25 @@ function extractRemediationContext(remediationPath) {
449
456
  }
450
457
  }
451
458
 
459
+ function detectStylingSystem(aiInput) {
460
+ const files = Array.isArray(aiInput?.files) ? aiInput.files : [];
461
+ const hasTailwind = files.some((f) => /tailwind\.config\.(js|ts|mjs|cjs)$/.test(f.filePath));
462
+ const hasCss = files.some((f) => /\.(css|scss|sass)$/.test(f.filePath));
463
+ if (hasTailwind) return "tailwind";
464
+ if (hasCss) return "css";
465
+ return "inline";
466
+ }
467
+
452
468
  async function callClaudeForPatch({ apiKey, model, aiInput, remediationPath }) {
453
469
  const remediationContext = extractRemediationContext(remediationPath);
470
+ const stylingSystem = detectStylingSystem(aiInput);
471
+
472
+ const styleInstruction =
473
+ stylingSystem === "tailwind"
474
+ ? "This project uses Tailwind CSS. Apply style fixes as Tailwind utility classes in the HTML/JSX file — do not write raw CSS."
475
+ : stylingSystem === "css"
476
+ ? "CSS/SCSS files are available in the files array. Prefer fixing visual issues (touch targets, color contrast, focus outlines) in the CSS/SCSS file using proper selectors rather than inline styles."
477
+ : "No CSS file was provided. Apply style fixes using inline style attributes in the HTML file.";
454
478
 
455
479
  const system = [
456
480
  "You are an accessibility fix engine.",
@@ -462,7 +486,7 @@ async function callClaudeForPatch({ apiKey, model, aiInput, remediationPath }) {
462
486
  "CRITICAL — search accuracy: the 'search' value must be a verbatim copy of a substring from the file content. Do not paraphrase, reformat, or reconstruct it — copy it character-for-character.",
463
487
  "For insertions (new element not yet in the file), anchor the search on the nearest existing surrounding element and include it in both search and replace.",
464
488
  "Do not create new files. Only write changes for filePaths listed in the files array.",
465
- "CSS files are never in the files array. Fix visual issues (touch targets, sizing) using inline style attributes or markup changes in the HTML file — never reference or create .css files.",
489
+ styleInstruction,
466
490
  ...(remediationContext ? ["", "## Project Context (from audit report)", remediationContext] : []),
467
491
  "Schema:",
468
492
  "{\"changes\":[{\"filePath\":\"...\",\"search\":\"...\",\"replace\":\"...\"}],\"verifyRule\":\"...\",\"verifyRoute\":\"...\",\"notes\":\"...\"}",