next-a11y 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +24 -19
- package/dist/cli/index.mjs +24 -19
- package/package.json +17 -8
package/dist/cli/index.js
CHANGED
|
@@ -23,6 +23,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
));
|
|
24
24
|
|
|
25
25
|
// src/cli/index.ts
|
|
26
|
+
var import_dotenv = require("dotenv");
|
|
26
27
|
var import_commander = require("commander");
|
|
27
28
|
|
|
28
29
|
// src/config/resolve.ts
|
|
@@ -1674,12 +1675,12 @@ function removeElement(file, line) {
|
|
|
1674
1675
|
}
|
|
1675
1676
|
|
|
1676
1677
|
// src/scan/scan.ts
|
|
1677
|
-
async function scan(targetPath,
|
|
1678
|
+
async function scan(targetPath, config2) {
|
|
1678
1679
|
const absPath = path4.resolve(targetPath);
|
|
1679
1680
|
const files = await discoverFiles(
|
|
1680
1681
|
absPath,
|
|
1681
|
-
|
|
1682
|
-
|
|
1682
|
+
config2.scanner.include,
|
|
1683
|
+
config2.scanner.exclude
|
|
1683
1684
|
);
|
|
1684
1685
|
if (files.length === 0) {
|
|
1685
1686
|
return {
|
|
@@ -1705,7 +1706,7 @@ async function scan(targetPath, config) {
|
|
|
1705
1706
|
} catch {
|
|
1706
1707
|
}
|
|
1707
1708
|
}
|
|
1708
|
-
const rules = getRulesForConfig(
|
|
1709
|
+
const rules = getRulesForConfig(config2.rules, config2.noAi);
|
|
1709
1710
|
const allViolations = [];
|
|
1710
1711
|
let elementsScanned = 0;
|
|
1711
1712
|
for (const sourceFile of project.getSourceFiles()) {
|
|
@@ -1719,11 +1720,11 @@ async function scan(targetPath, config) {
|
|
|
1719
1720
|
elementsScanned += sourceFile.getDescendants().length;
|
|
1720
1721
|
}
|
|
1721
1722
|
let fixedCount = 0;
|
|
1722
|
-
if (
|
|
1723
|
+
if (config2.fix) {
|
|
1723
1724
|
for (const violation of allViolations) {
|
|
1724
1725
|
if (!violation.fix) continue;
|
|
1725
1726
|
const rule = rules.find((r) => r.id === violation.rule);
|
|
1726
|
-
if (
|
|
1727
|
+
if (config2.noAi && rule?.type === "ai") continue;
|
|
1727
1728
|
try {
|
|
1728
1729
|
const sourceFile = project.getSourceFile(violation.filePath);
|
|
1729
1730
|
if (!sourceFile) continue;
|
|
@@ -1736,10 +1737,10 @@ async function scan(targetPath, config) {
|
|
|
1736
1737
|
await project.save();
|
|
1737
1738
|
}
|
|
1738
1739
|
}
|
|
1739
|
-
const remainingViolations =
|
|
1740
|
+
const remainingViolations = config2.fix ? allViolations.filter((v) => !v.fix || config2.noAi && rules.find((r) => r.id === v.rule)?.type === "ai") : allViolations;
|
|
1740
1741
|
const score = computeScore(remainingViolations);
|
|
1741
|
-
const previousScore = loadPreviousScore(
|
|
1742
|
-
savePreviousScore(
|
|
1742
|
+
const previousScore = loadPreviousScore(config2.cache);
|
|
1743
|
+
savePreviousScore(config2.cache, score);
|
|
1743
1744
|
return {
|
|
1744
1745
|
violations: allViolations,
|
|
1745
1746
|
filesScanned: files.length,
|
|
@@ -1895,7 +1896,7 @@ function formatRuleDescription(rule) {
|
|
|
1895
1896
|
function registerScanCommand(program2) {
|
|
1896
1897
|
program2.command("scan").description("Scan files for accessibility issues").argument("<path>", "Path to scan").option("--fix", "Auto-fix issues").option("-i, --interactive", "Review each fix interactively").option("--no-ai", "Skip AI-powered fixes").option("--provider <provider>", "Override AI provider").option("--model <model>", "Override AI model").option("--min-score <score>", "Minimum score threshold (exit code 1 if below)", parseInt).action(async (targetPath, options) => {
|
|
1897
1898
|
const fileConfig = await loadConfigFile(process.cwd());
|
|
1898
|
-
const
|
|
1899
|
+
const config2 = resolveConfig(fileConfig, {
|
|
1899
1900
|
fix: options.fix,
|
|
1900
1901
|
interactive: options.interactive,
|
|
1901
1902
|
noAi: !options.ai,
|
|
@@ -1904,11 +1905,11 @@ function registerScanCommand(program2) {
|
|
|
1904
1905
|
model: options.model,
|
|
1905
1906
|
minScore: options.minScore
|
|
1906
1907
|
});
|
|
1907
|
-
const result = await scan(targetPath,
|
|
1908
|
-
console.log(formatReport(result,
|
|
1909
|
-
if (
|
|
1908
|
+
const result = await scan(targetPath, config2);
|
|
1909
|
+
console.log(formatReport(result, config2.fix));
|
|
1910
|
+
if (config2.minScore !== void 0 && result.score < config2.minScore) {
|
|
1910
1911
|
console.error(
|
|
1911
|
-
` Score ${result.score} is below minimum threshold ${
|
|
1912
|
+
` Score ${result.score} is below minimum threshold ${config2.minScore}`
|
|
1912
1913
|
);
|
|
1913
1914
|
process.exit(1);
|
|
1914
1915
|
}
|
|
@@ -2148,21 +2149,21 @@ function registerCacheCommand(program2) {
|
|
|
2148
2149
|
const cache = program2.command("cache").description("Manage the AI result cache");
|
|
2149
2150
|
cache.command("stats").description("Show cache statistics").action(async () => {
|
|
2150
2151
|
const fileConfig = await loadConfigFile(process.cwd());
|
|
2151
|
-
const
|
|
2152
|
-
const fsCache = new FsCache(
|
|
2152
|
+
const config2 = resolveConfig(fileConfig);
|
|
2153
|
+
const fsCache = new FsCache(config2.cache);
|
|
2153
2154
|
const stats = fsCache.stats();
|
|
2154
2155
|
console.log(import_picocolors3.default.bold("\n Cache Statistics\n"));
|
|
2155
2156
|
console.log(` Entries: ${stats.entries}`);
|
|
2156
2157
|
console.log(
|
|
2157
2158
|
` Size: ${formatBytes(stats.sizeBytes)}`
|
|
2158
2159
|
);
|
|
2159
|
-
console.log(` Path: ${
|
|
2160
|
+
console.log(` Path: ${config2.cache}/cache.json`);
|
|
2160
2161
|
console.log("");
|
|
2161
2162
|
});
|
|
2162
2163
|
cache.command("clear").description("Clear the cache").action(async () => {
|
|
2163
2164
|
const fileConfig = await loadConfigFile(process.cwd());
|
|
2164
|
-
const
|
|
2165
|
-
const fsCache = new FsCache(
|
|
2165
|
+
const config2 = resolveConfig(fileConfig);
|
|
2166
|
+
const fsCache = new FsCache(config2.cache);
|
|
2166
2167
|
fsCache.clear();
|
|
2167
2168
|
console.log(import_picocolors3.default.green("\n Cache cleared.\n"));
|
|
2168
2169
|
});
|
|
@@ -2175,6 +2176,10 @@ function formatBytes(bytes) {
|
|
|
2175
2176
|
}
|
|
2176
2177
|
|
|
2177
2178
|
// src/cli/index.ts
|
|
2179
|
+
(0, import_dotenv.config)({ path: ".env", override: false });
|
|
2180
|
+
(0, import_dotenv.config)({ path: ".env.local", override: true });
|
|
2181
|
+
(0, import_dotenv.config)({ path: ".env.development", override: true });
|
|
2182
|
+
(0, import_dotenv.config)({ path: ".env.development.local", override: true });
|
|
2178
2183
|
var program = new import_commander.Command();
|
|
2179
2184
|
program.name("next-a11y").description("AI-powered accessibility codemod for Next.js").version("0.1.0");
|
|
2180
2185
|
registerScanCommand(program);
|
package/dist/cli/index.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
} from "../chunk-PE4WYXR5.mjs";
|
|
7
7
|
|
|
8
8
|
// src/cli/index.ts
|
|
9
|
+
import { config } from "dotenv";
|
|
9
10
|
import { Command } from "commander";
|
|
10
11
|
|
|
11
12
|
// src/config/resolve.ts
|
|
@@ -1615,12 +1616,12 @@ function removeElement(file, line) {
|
|
|
1615
1616
|
}
|
|
1616
1617
|
|
|
1617
1618
|
// src/scan/scan.ts
|
|
1618
|
-
async function scan(targetPath,
|
|
1619
|
+
async function scan(targetPath, config2) {
|
|
1619
1620
|
const absPath = path4.resolve(targetPath);
|
|
1620
1621
|
const files = await discoverFiles(
|
|
1621
1622
|
absPath,
|
|
1622
|
-
|
|
1623
|
-
|
|
1623
|
+
config2.scanner.include,
|
|
1624
|
+
config2.scanner.exclude
|
|
1624
1625
|
);
|
|
1625
1626
|
if (files.length === 0) {
|
|
1626
1627
|
return {
|
|
@@ -1646,7 +1647,7 @@ async function scan(targetPath, config) {
|
|
|
1646
1647
|
} catch {
|
|
1647
1648
|
}
|
|
1648
1649
|
}
|
|
1649
|
-
const rules = getRulesForConfig(
|
|
1650
|
+
const rules = getRulesForConfig(config2.rules, config2.noAi);
|
|
1650
1651
|
const allViolations = [];
|
|
1651
1652
|
let elementsScanned = 0;
|
|
1652
1653
|
for (const sourceFile of project.getSourceFiles()) {
|
|
@@ -1660,11 +1661,11 @@ async function scan(targetPath, config) {
|
|
|
1660
1661
|
elementsScanned += sourceFile.getDescendants().length;
|
|
1661
1662
|
}
|
|
1662
1663
|
let fixedCount = 0;
|
|
1663
|
-
if (
|
|
1664
|
+
if (config2.fix) {
|
|
1664
1665
|
for (const violation of allViolations) {
|
|
1665
1666
|
if (!violation.fix) continue;
|
|
1666
1667
|
const rule = rules.find((r) => r.id === violation.rule);
|
|
1667
|
-
if (
|
|
1668
|
+
if (config2.noAi && rule?.type === "ai") continue;
|
|
1668
1669
|
try {
|
|
1669
1670
|
const sourceFile = project.getSourceFile(violation.filePath);
|
|
1670
1671
|
if (!sourceFile) continue;
|
|
@@ -1677,10 +1678,10 @@ async function scan(targetPath, config) {
|
|
|
1677
1678
|
await project.save();
|
|
1678
1679
|
}
|
|
1679
1680
|
}
|
|
1680
|
-
const remainingViolations =
|
|
1681
|
+
const remainingViolations = config2.fix ? allViolations.filter((v) => !v.fix || config2.noAi && rules.find((r) => r.id === v.rule)?.type === "ai") : allViolations;
|
|
1681
1682
|
const score = computeScore(remainingViolations);
|
|
1682
|
-
const previousScore = loadPreviousScore(
|
|
1683
|
-
savePreviousScore(
|
|
1683
|
+
const previousScore = loadPreviousScore(config2.cache);
|
|
1684
|
+
savePreviousScore(config2.cache, score);
|
|
1684
1685
|
return {
|
|
1685
1686
|
violations: allViolations,
|
|
1686
1687
|
filesScanned: files.length,
|
|
@@ -1836,7 +1837,7 @@ function formatRuleDescription(rule) {
|
|
|
1836
1837
|
function registerScanCommand(program2) {
|
|
1837
1838
|
program2.command("scan").description("Scan files for accessibility issues").argument("<path>", "Path to scan").option("--fix", "Auto-fix issues").option("-i, --interactive", "Review each fix interactively").option("--no-ai", "Skip AI-powered fixes").option("--provider <provider>", "Override AI provider").option("--model <model>", "Override AI model").option("--min-score <score>", "Minimum score threshold (exit code 1 if below)", parseInt).action(async (targetPath, options) => {
|
|
1838
1839
|
const fileConfig = await loadConfigFile(process.cwd());
|
|
1839
|
-
const
|
|
1840
|
+
const config2 = resolveConfig(fileConfig, {
|
|
1840
1841
|
fix: options.fix,
|
|
1841
1842
|
interactive: options.interactive,
|
|
1842
1843
|
noAi: !options.ai,
|
|
@@ -1845,11 +1846,11 @@ function registerScanCommand(program2) {
|
|
|
1845
1846
|
model: options.model,
|
|
1846
1847
|
minScore: options.minScore
|
|
1847
1848
|
});
|
|
1848
|
-
const result = await scan(targetPath,
|
|
1849
|
-
console.log(formatReport(result,
|
|
1850
|
-
if (
|
|
1849
|
+
const result = await scan(targetPath, config2);
|
|
1850
|
+
console.log(formatReport(result, config2.fix));
|
|
1851
|
+
if (config2.minScore !== void 0 && result.score < config2.minScore) {
|
|
1851
1852
|
console.error(
|
|
1852
|
-
` Score ${result.score} is below minimum threshold ${
|
|
1853
|
+
` Score ${result.score} is below minimum threshold ${config2.minScore}`
|
|
1853
1854
|
);
|
|
1854
1855
|
process.exit(1);
|
|
1855
1856
|
}
|
|
@@ -2089,21 +2090,21 @@ function registerCacheCommand(program2) {
|
|
|
2089
2090
|
const cache = program2.command("cache").description("Manage the AI result cache");
|
|
2090
2091
|
cache.command("stats").description("Show cache statistics").action(async () => {
|
|
2091
2092
|
const fileConfig = await loadConfigFile(process.cwd());
|
|
2092
|
-
const
|
|
2093
|
-
const fsCache = new FsCache(
|
|
2093
|
+
const config2 = resolveConfig(fileConfig);
|
|
2094
|
+
const fsCache = new FsCache(config2.cache);
|
|
2094
2095
|
const stats = fsCache.stats();
|
|
2095
2096
|
console.log(pc3.bold("\n Cache Statistics\n"));
|
|
2096
2097
|
console.log(` Entries: ${stats.entries}`);
|
|
2097
2098
|
console.log(
|
|
2098
2099
|
` Size: ${formatBytes(stats.sizeBytes)}`
|
|
2099
2100
|
);
|
|
2100
|
-
console.log(` Path: ${
|
|
2101
|
+
console.log(` Path: ${config2.cache}/cache.json`);
|
|
2101
2102
|
console.log("");
|
|
2102
2103
|
});
|
|
2103
2104
|
cache.command("clear").description("Clear the cache").action(async () => {
|
|
2104
2105
|
const fileConfig = await loadConfigFile(process.cwd());
|
|
2105
|
-
const
|
|
2106
|
-
const fsCache = new FsCache(
|
|
2106
|
+
const config2 = resolveConfig(fileConfig);
|
|
2107
|
+
const fsCache = new FsCache(config2.cache);
|
|
2107
2108
|
fsCache.clear();
|
|
2108
2109
|
console.log(pc3.green("\n Cache cleared.\n"));
|
|
2109
2110
|
});
|
|
@@ -2116,6 +2117,10 @@ function formatBytes(bytes) {
|
|
|
2116
2117
|
}
|
|
2117
2118
|
|
|
2118
2119
|
// src/cli/index.ts
|
|
2120
|
+
config({ path: ".env", override: false });
|
|
2121
|
+
config({ path: ".env.local", override: true });
|
|
2122
|
+
config({ path: ".env.development", override: true });
|
|
2123
|
+
config({ path: ".env.development.local", override: true });
|
|
2119
2124
|
var program = new Command();
|
|
2120
2125
|
program.name("next-a11y").description("AI-powered accessibility codemod for Next.js").version("0.1.0");
|
|
2121
2126
|
registerScanCommand(program);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-a11y",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "AI-powered accessibility codemod for Next.js",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -36,9 +36,10 @@
|
|
|
36
36
|
"license": "MIT",
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"ai": "^4.0.0",
|
|
39
|
-
"ts-morph": "^24.0.0",
|
|
40
39
|
"commander": "^12.0.0",
|
|
41
|
-
"
|
|
40
|
+
"dotenv": "^17.3.1",
|
|
41
|
+
"picocolors": "^1.1.0",
|
|
42
|
+
"ts-morph": "^24.0.0"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
45
|
"tsup": "^8.0.0",
|
|
@@ -46,15 +47,23 @@
|
|
|
46
47
|
"vitest": "^2.0.0"
|
|
47
48
|
},
|
|
48
49
|
"peerDependencies": {
|
|
49
|
-
"@ai-sdk/openai": ">=1.0.0",
|
|
50
50
|
"@ai-sdk/anthropic": ">=1.0.0",
|
|
51
51
|
"@ai-sdk/google": ">=1.0.0",
|
|
52
|
+
"@ai-sdk/openai": ">=1.0.0",
|
|
52
53
|
"ollama-ai-provider": ">=1.0.0"
|
|
53
54
|
},
|
|
54
55
|
"peerDependenciesMeta": {
|
|
55
|
-
"@ai-sdk/openai": {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"
|
|
56
|
+
"@ai-sdk/openai": {
|
|
57
|
+
"optional": true
|
|
58
|
+
},
|
|
59
|
+
"@ai-sdk/anthropic": {
|
|
60
|
+
"optional": true
|
|
61
|
+
},
|
|
62
|
+
"@ai-sdk/google": {
|
|
63
|
+
"optional": true
|
|
64
|
+
},
|
|
65
|
+
"ollama-ai-provider": {
|
|
66
|
+
"optional": true
|
|
67
|
+
}
|
|
59
68
|
}
|
|
60
69
|
}
|