@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
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
489
|
+
styleInstruction,
|
|
466
490
|
...(remediationContext ? ["", "## Project Context (from audit report)", remediationContext] : []),
|
|
467
491
|
"Schema:",
|
|
468
492
|
"{\"changes\":[{\"filePath\":\"...\",\"search\":\"...\",\"replace\":\"...\"}],\"verifyRule\":\"...\",\"verifyRoute\":\"...\",\"notes\":\"...\"}",
|