@empline/preflight 1.1.55 → 1.1.57
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/checks/accessibility/accessibility-validation.d.ts +10 -0
- package/dist/checks/accessibility/accessibility-validation.d.ts.map +1 -0
- package/dist/checks/accessibility/accessibility-validation.js +472 -0
- package/dist/checks/accessibility/accessibility-validation.js.map +1 -0
- package/dist/checks/database/prisma-naming-conventions.d.ts +10 -0
- package/dist/checks/database/prisma-naming-conventions.d.ts.map +1 -0
- package/dist/checks/database/prisma-naming-conventions.js +456 -0
- package/dist/checks/database/prisma-naming-conventions.js.map +1 -0
- package/dist/checks/react/vercel-react-best-practices.d.ts.map +1 -1
- package/dist/checks/react/vercel-react-best-practices.js +60 -8
- package/dist/checks/react/vercel-react-best-practices.js.map +1 -1
- package/dist/checks/seo/seo-validation.d.ts +10 -0
- package/dist/checks/seo/seo-validation.d.ts.map +1 -0
- package/dist/checks/seo/seo-validation.js +497 -0
- package/dist/checks/seo/seo-validation.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { PreflightCheckResult } from "../../core/types";
|
|
3
|
+
export declare const id = "accessibility/accessibility-validation";
|
|
4
|
+
export declare const name = "Accessibility Validation";
|
|
5
|
+
export declare const description = "Validates accessibility best practices (images, forms, ARIA, headings)";
|
|
6
|
+
export declare const category = "accessibility";
|
|
7
|
+
export declare const blocking = true;
|
|
8
|
+
export declare const tags: string[];
|
|
9
|
+
export declare function run(): Promise<PreflightCheckResult>;
|
|
10
|
+
//# sourceMappingURL=accessibility-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessibility-validation.d.ts","sourceRoot":"","sources":["../../../src/checks/accessibility/accessibility-validation.ts"],"names":[],"mappings":";AAiCA,OAAO,EAAE,oBAAoB,EAAoB,MAAM,kBAAkB,CAAC;AAG1E,eAAO,MAAM,EAAE,2CAA2C,CAAC;AAC3D,eAAO,MAAM,IAAI,6BAA6B,CAAC;AAC/C,eAAO,MAAM,WAAW,2EAA2E,CAAC;AACpG,eAAO,MAAM,QAAQ,kBAAkB,CAAC;AACxC,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,IAAI,UAA+D,CAAC;AAuRjF,wBAAsB,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAqEzD"}
|
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.tags = exports.blocking = exports.category = exports.description = exports.name = exports.id = void 0;
|
|
38
|
+
exports.run = run;
|
|
39
|
+
/**
|
|
40
|
+
* Accessibility Validation Preflight (BLOCKING)
|
|
41
|
+
*
|
|
42
|
+
* Validates accessibility best practices in React/Next.js components:
|
|
43
|
+
*
|
|
44
|
+
* 1. Image Accessibility:
|
|
45
|
+
* - All <img> tags must have alt attribute
|
|
46
|
+
* - Next.js <Image> components must have alt attribute
|
|
47
|
+
* - Decorative images should have alt=""
|
|
48
|
+
*
|
|
49
|
+
* 2. Form Accessibility:
|
|
50
|
+
* - Form inputs must have associated labels (htmlFor/id or aria-label)
|
|
51
|
+
* - Buttons must have accessible text (children or aria-label)
|
|
52
|
+
* - Required fields should have aria-required
|
|
53
|
+
*
|
|
54
|
+
* 3. Interactive Element Accessibility:
|
|
55
|
+
* - onClick handlers on non-interactive elements need role and keyboard support
|
|
56
|
+
* - Links must have meaningful text (not just "click here")
|
|
57
|
+
* - Buttons should not be empty
|
|
58
|
+
*
|
|
59
|
+
* 4. ARIA Validation:
|
|
60
|
+
* - aria-* attributes must have valid values
|
|
61
|
+
* - role attributes must be valid ARIA roles
|
|
62
|
+
* - aria-hidden elements should not contain focusable content
|
|
63
|
+
*
|
|
64
|
+
* 5. Heading Structure:
|
|
65
|
+
* - Pages should have h1
|
|
66
|
+
* - Heading levels should not skip (h1 -> h3)
|
|
67
|
+
*/
|
|
68
|
+
const fs = __importStar(require("node:fs"));
|
|
69
|
+
const path = __importStar(require("node:path"));
|
|
70
|
+
const glob_1 = require("glob");
|
|
71
|
+
const console_chars_1 = require("../../utils/console-chars");
|
|
72
|
+
exports.id = "accessibility/accessibility-validation";
|
|
73
|
+
exports.name = "Accessibility Validation";
|
|
74
|
+
exports.description = "Validates accessibility best practices (images, forms, ARIA, headings)";
|
|
75
|
+
exports.category = "accessibility";
|
|
76
|
+
exports.blocking = true;
|
|
77
|
+
exports.tags = ["accessibility", "a11y", "wcag", "aria", "images", "forms"];
|
|
78
|
+
// Valid ARIA roles
|
|
79
|
+
const VALID_ROLES = new Set([
|
|
80
|
+
"alert", "alertdialog", "application", "article", "banner", "button",
|
|
81
|
+
"cell", "checkbox", "columnheader", "combobox", "complementary",
|
|
82
|
+
"contentinfo", "definition", "dialog", "directory", "document",
|
|
83
|
+
"feed", "figure", "form", "grid", "gridcell", "group", "heading",
|
|
84
|
+
"img", "link", "list", "listbox", "listitem", "log", "main",
|
|
85
|
+
"marquee", "math", "menu", "menubar", "menuitem", "menuitemcheckbox",
|
|
86
|
+
"menuitemradio", "navigation", "none", "note", "option", "presentation",
|
|
87
|
+
"progressbar", "radio", "radiogroup", "region", "row", "rowgroup",
|
|
88
|
+
"rowheader", "scrollbar", "search", "searchbox", "separator",
|
|
89
|
+
"slider", "spinbutton", "status", "switch", "tab", "table",
|
|
90
|
+
"tablist", "tabpanel", "term", "textbox", "timer", "toolbar",
|
|
91
|
+
"tooltip", "tree", "treegrid", "treeitem",
|
|
92
|
+
]);
|
|
93
|
+
// Patterns for meaningless link text
|
|
94
|
+
const MEANINGLESS_LINK_TEXT = [
|
|
95
|
+
/^click\s*here$/i,
|
|
96
|
+
/^here$/i,
|
|
97
|
+
/^read\s*more$/i,
|
|
98
|
+
/^learn\s*more$/i,
|
|
99
|
+
/^more$/i,
|
|
100
|
+
/^link$/i,
|
|
101
|
+
];
|
|
102
|
+
function getLineNumber(content, index) {
|
|
103
|
+
return content.substring(0, index).split("\n").length;
|
|
104
|
+
}
|
|
105
|
+
function checkImageAccessibility(content, filePath) {
|
|
106
|
+
const issues = [];
|
|
107
|
+
// Check <img> tags without alt
|
|
108
|
+
const imgRegex = /<img\s+(?![^>]*\balt\s*=)[^>]*>/gi;
|
|
109
|
+
let match;
|
|
110
|
+
while ((match = imgRegex.exec(content)) !== null) {
|
|
111
|
+
issues.push({
|
|
112
|
+
rule: "img-alt-required",
|
|
113
|
+
message: "<img> tag missing alt attribute",
|
|
114
|
+
file: filePath,
|
|
115
|
+
line: getLineNumber(content, match.index),
|
|
116
|
+
severity: "error",
|
|
117
|
+
suggestion: 'Add alt="description" or alt="" for decorative images',
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
// Check Next.js <Image> components without alt
|
|
121
|
+
const nextImageRegex = /<Image\s+(?![^>]*\balt\s*=)[^>]*\/?>/gi;
|
|
122
|
+
while ((match = nextImageRegex.exec(content)) !== null) {
|
|
123
|
+
issues.push({
|
|
124
|
+
rule: "next-image-alt-required",
|
|
125
|
+
message: "Next.js <Image> component missing alt attribute",
|
|
126
|
+
file: filePath,
|
|
127
|
+
line: getLineNumber(content, match.index),
|
|
128
|
+
severity: "error",
|
|
129
|
+
suggestion: 'Add alt="description" or alt="" for decorative images',
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return issues;
|
|
133
|
+
}
|
|
134
|
+
function checkFormAccessibility(content, filePath) {
|
|
135
|
+
const issues = [];
|
|
136
|
+
// Check for inputs without labels or aria-label
|
|
137
|
+
// This is a simplified check - looks for <input> not followed by aria-label or aria-labelledby
|
|
138
|
+
const inputRegex = /<input\s+(?![^>]*(?:aria-label|aria-labelledby)\s*=)[^>]*type\s*=\s*["'](?!hidden|submit|button|reset)[^"']*["'][^>]*>/gi;
|
|
139
|
+
let match;
|
|
140
|
+
while ((match = inputRegex.exec(content)) !== null) {
|
|
141
|
+
// Check if there's an id and if content has a matching htmlFor
|
|
142
|
+
const idMatch = match[0].match(/id\s*=\s*["']([^"']+)["']/);
|
|
143
|
+
if (idMatch) {
|
|
144
|
+
const labelRegex = new RegExp(`htmlFor\\s*=\\s*["']${idMatch[1]}["']`, "i");
|
|
145
|
+
if (!labelRegex.test(content)) {
|
|
146
|
+
issues.push({
|
|
147
|
+
rule: "input-label-required",
|
|
148
|
+
message: `Input with id="${idMatch[1]}" has no associated label`,
|
|
149
|
+
file: filePath,
|
|
150
|
+
line: getLineNumber(content, match.index),
|
|
151
|
+
severity: "warning",
|
|
152
|
+
suggestion: `Add <label htmlFor="${idMatch[1]}"> or aria-label attribute`,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else if (!match[0].includes("aria-label")) {
|
|
157
|
+
issues.push({
|
|
158
|
+
rule: "input-label-required",
|
|
159
|
+
message: "Input has no id for label association and no aria-label",
|
|
160
|
+
file: filePath,
|
|
161
|
+
line: getLineNumber(content, match.index),
|
|
162
|
+
severity: "warning",
|
|
163
|
+
suggestion: "Add id with matching label htmlFor, or add aria-label",
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Check for empty buttons
|
|
168
|
+
const emptyButtonRegex = /<button[^>]*>\s*<\/button>/gi;
|
|
169
|
+
while ((match = emptyButtonRegex.exec(content)) !== null) {
|
|
170
|
+
if (!match[0].includes("aria-label")) {
|
|
171
|
+
issues.push({
|
|
172
|
+
rule: "button-text-required",
|
|
173
|
+
message: "Empty button has no accessible text",
|
|
174
|
+
file: filePath,
|
|
175
|
+
line: getLineNumber(content, match.index),
|
|
176
|
+
severity: "error",
|
|
177
|
+
suggestion: "Add button text content or aria-label",
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Check for icon-only buttons without aria-label
|
|
182
|
+
const iconButtonRegex = /<button[^>]*>\s*<(?:svg|Icon|[A-Z]\w*Icon)[^>]*\/?>\s*<\/button>/gi;
|
|
183
|
+
while ((match = iconButtonRegex.exec(content)) !== null) {
|
|
184
|
+
if (!match[0].includes("aria-label") && !match[0].includes("title")) {
|
|
185
|
+
issues.push({
|
|
186
|
+
rule: "icon-button-label-required",
|
|
187
|
+
message: "Icon-only button has no accessible text",
|
|
188
|
+
file: filePath,
|
|
189
|
+
line: getLineNumber(content, match.index),
|
|
190
|
+
severity: "error",
|
|
191
|
+
suggestion: 'Add aria-label="action description"',
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return issues;
|
|
196
|
+
}
|
|
197
|
+
function checkInteractiveElements(content, filePath) {
|
|
198
|
+
const issues = [];
|
|
199
|
+
// Check for onClick on non-interactive elements without role
|
|
200
|
+
const onClickDivRegex = /<div\s+(?![^>]*role\s*=)[^>]*onClick\s*=/gi;
|
|
201
|
+
let match;
|
|
202
|
+
while ((match = onClickDivRegex.exec(content)) !== null) {
|
|
203
|
+
issues.push({
|
|
204
|
+
rule: "div-onclick-needs-role",
|
|
205
|
+
message: "<div> with onClick needs role attribute for accessibility",
|
|
206
|
+
file: filePath,
|
|
207
|
+
line: getLineNumber(content, match.index),
|
|
208
|
+
severity: "warning",
|
|
209
|
+
suggestion: 'Add role="button" and tabIndex={0} and onKeyDown handler',
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
// Check for spans with onClick
|
|
213
|
+
const onClickSpanRegex = /<span\s+(?![^>]*role\s*=)[^>]*onClick\s*=/gi;
|
|
214
|
+
while ((match = onClickSpanRegex.exec(content)) !== null) {
|
|
215
|
+
issues.push({
|
|
216
|
+
rule: "span-onclick-needs-role",
|
|
217
|
+
message: "<span> with onClick needs role attribute for accessibility",
|
|
218
|
+
file: filePath,
|
|
219
|
+
line: getLineNumber(content, match.index),
|
|
220
|
+
severity: "warning",
|
|
221
|
+
suggestion: 'Add role="button" and tabIndex={0} and onKeyDown handler',
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
// Check for meaningless link text
|
|
225
|
+
for (const pattern of MEANINGLESS_LINK_TEXT) {
|
|
226
|
+
const linkRegex = new RegExp(`<(?:a|Link)[^>]*>\\s*${pattern.source}\\s*</(?:a|Link)>`, "gi");
|
|
227
|
+
while ((match = linkRegex.exec(content)) !== null) {
|
|
228
|
+
issues.push({
|
|
229
|
+
rule: "meaningful-link-text",
|
|
230
|
+
message: "Link has non-descriptive text",
|
|
231
|
+
file: filePath,
|
|
232
|
+
line: getLineNumber(content, match.index),
|
|
233
|
+
severity: "warning",
|
|
234
|
+
suggestion: "Use descriptive link text that explains the destination",
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return issues;
|
|
239
|
+
}
|
|
240
|
+
function checkAriaAttributes(content, filePath) {
|
|
241
|
+
const issues = [];
|
|
242
|
+
// Check for invalid role values
|
|
243
|
+
const roleRegex = /role\s*=\s*["']([^"']+)["']/gi;
|
|
244
|
+
let match;
|
|
245
|
+
while ((match = roleRegex.exec(content)) !== null) {
|
|
246
|
+
const role = match[1].toLowerCase();
|
|
247
|
+
if (!VALID_ROLES.has(role)) {
|
|
248
|
+
issues.push({
|
|
249
|
+
rule: "valid-aria-role",
|
|
250
|
+
message: `Invalid ARIA role: "${role}"`,
|
|
251
|
+
file: filePath,
|
|
252
|
+
line: getLineNumber(content, match.index),
|
|
253
|
+
severity: "error",
|
|
254
|
+
suggestion: `Use a valid ARIA role (e.g., button, link, dialog, etc.)`,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Check for aria-hidden on elements with focusable content
|
|
259
|
+
const ariaHiddenRegex = /aria-hidden\s*=\s*["']true["'][^>]*>[\s\S]*?<(?:button|a|input|select|textarea|Link)\s/gi;
|
|
260
|
+
while ((match = ariaHiddenRegex.exec(content)) !== null) {
|
|
261
|
+
issues.push({
|
|
262
|
+
rule: "aria-hidden-focusable",
|
|
263
|
+
message: "aria-hidden element contains focusable content",
|
|
264
|
+
file: filePath,
|
|
265
|
+
line: getLineNumber(content, match.index),
|
|
266
|
+
severity: "error",
|
|
267
|
+
suggestion: "Remove focusable elements from aria-hidden containers or add tabIndex={-1}",
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
// Check for aria-label on elements that don't support it (non-interactive)
|
|
271
|
+
// This is a simplified check
|
|
272
|
+
const ariaLabelOnDivRegex = /<div\s+(?![^>]*role\s*=)[^>]*aria-label\s*=/gi;
|
|
273
|
+
while ((match = ariaLabelOnDivRegex.exec(content)) !== null) {
|
|
274
|
+
issues.push({
|
|
275
|
+
rule: "aria-label-valid-element",
|
|
276
|
+
message: "aria-label on <div> without role may not be announced",
|
|
277
|
+
file: filePath,
|
|
278
|
+
line: getLineNumber(content, match.index),
|
|
279
|
+
severity: "warning",
|
|
280
|
+
suggestion: "Add a role attribute or use aria-labelledby instead",
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
return issues;
|
|
284
|
+
}
|
|
285
|
+
function checkHeadingStructure(content, filePath) {
|
|
286
|
+
const issues = [];
|
|
287
|
+
// Find all heading tags
|
|
288
|
+
const headingRegex = /<h([1-6])[^>]*>/gi;
|
|
289
|
+
const headings = [];
|
|
290
|
+
let match;
|
|
291
|
+
while ((match = headingRegex.exec(content)) !== null) {
|
|
292
|
+
headings.push({
|
|
293
|
+
level: parseInt(match[1], 10),
|
|
294
|
+
index: match.index,
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
if (headings.length === 0) {
|
|
298
|
+
return issues; // No headings to check
|
|
299
|
+
}
|
|
300
|
+
// Check for skipped heading levels
|
|
301
|
+
for (let i = 1; i < headings.length; i++) {
|
|
302
|
+
const prev = headings[i - 1];
|
|
303
|
+
const curr = headings[i];
|
|
304
|
+
// If going deeper, shouldn't skip levels (h1 -> h3 is bad, h1 -> h2 is fine)
|
|
305
|
+
if (curr.level > prev.level && curr.level - prev.level > 1) {
|
|
306
|
+
issues.push({
|
|
307
|
+
rule: "heading-order",
|
|
308
|
+
message: `Heading level skipped: h${prev.level} to h${curr.level}`,
|
|
309
|
+
file: filePath,
|
|
310
|
+
line: getLineNumber(content, curr.index),
|
|
311
|
+
severity: "warning",
|
|
312
|
+
suggestion: `Use h${prev.level + 1} instead of h${curr.level}`,
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return issues;
|
|
317
|
+
}
|
|
318
|
+
async function run() {
|
|
319
|
+
const startTime = Date.now();
|
|
320
|
+
const findings = [];
|
|
321
|
+
// Find all TSX files
|
|
322
|
+
const files = await (0, glob_1.glob)([
|
|
323
|
+
"app/**/*.tsx",
|
|
324
|
+
"components/**/*.tsx",
|
|
325
|
+
"src/**/*.tsx",
|
|
326
|
+
], {
|
|
327
|
+
cwd: process.cwd(),
|
|
328
|
+
ignore: [
|
|
329
|
+
"**/node_modules/**",
|
|
330
|
+
"**/*.test.tsx",
|
|
331
|
+
"**/*.spec.tsx",
|
|
332
|
+
"**/*.stories.tsx",
|
|
333
|
+
],
|
|
334
|
+
});
|
|
335
|
+
let filesChecked = 0;
|
|
336
|
+
const allIssues = [];
|
|
337
|
+
for (const file of files) {
|
|
338
|
+
const filePath = path.join(process.cwd(), file);
|
|
339
|
+
if (!fs.existsSync(filePath))
|
|
340
|
+
continue;
|
|
341
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
342
|
+
// Skip files with accessibility ignore comment
|
|
343
|
+
if (content.includes("a11y-ignore") || content.includes("accessibility-ignore")) {
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
filesChecked++;
|
|
347
|
+
// Run all accessibility checks
|
|
348
|
+
allIssues.push(...checkImageAccessibility(content, file));
|
|
349
|
+
allIssues.push(...checkFormAccessibility(content, file));
|
|
350
|
+
allIssues.push(...checkInteractiveElements(content, file));
|
|
351
|
+
allIssues.push(...checkAriaAttributes(content, file));
|
|
352
|
+
allIssues.push(...checkHeadingStructure(content, file));
|
|
353
|
+
}
|
|
354
|
+
// Convert to findings
|
|
355
|
+
for (const issue of allIssues) {
|
|
356
|
+
findings.push({
|
|
357
|
+
level: issue.severity,
|
|
358
|
+
message: issue.message,
|
|
359
|
+
file: issue.file,
|
|
360
|
+
startLine: issue.line,
|
|
361
|
+
ruleId: issue.rule,
|
|
362
|
+
suggestion: issue.suggestion,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
const errors = findings.filter(f => f.level === "error");
|
|
366
|
+
const warnings = findings.filter(f => f.level === "warning");
|
|
367
|
+
return {
|
|
368
|
+
passed: errors.length === 0,
|
|
369
|
+
findings,
|
|
370
|
+
duration: Date.now() - startTime,
|
|
371
|
+
metadata: {
|
|
372
|
+
filesChecked,
|
|
373
|
+
totalIssues: allIssues.length,
|
|
374
|
+
errors: errors.length,
|
|
375
|
+
warnings: warnings.length,
|
|
376
|
+
},
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
async function main() {
|
|
380
|
+
console.log(`\n${console_chars_1.emoji.accessibility} ACCESSIBILITY VALIDATION`);
|
|
381
|
+
console.log((0, console_chars_1.createDivider)(65, "heavy"));
|
|
382
|
+
const result = await run();
|
|
383
|
+
const { filesChecked, totalIssues, errors, warnings } = result.metadata || {};
|
|
384
|
+
console.log(`\n${console_chars_1.emoji.search} Checking accessibility...`);
|
|
385
|
+
console.log(` Files checked: ${filesChecked}`);
|
|
386
|
+
console.log(` Total issues: ${totalIssues}`);
|
|
387
|
+
console.log(`\n${console_chars_1.emoji.chart} Summary:`);
|
|
388
|
+
console.log(` Errors: ${errors}`);
|
|
389
|
+
console.log(` Warnings: ${warnings}`);
|
|
390
|
+
if (result.passed && warnings === 0) {
|
|
391
|
+
console.log(`\n${console_chars_1.emoji.success} ACCESSIBILITY VALIDATION PASSED`);
|
|
392
|
+
console.log(`\nAll components follow accessibility best practices.`);
|
|
393
|
+
process.exit(0);
|
|
394
|
+
}
|
|
395
|
+
// Group findings by rule
|
|
396
|
+
const findingsByRule = new Map();
|
|
397
|
+
for (const finding of result.findings) {
|
|
398
|
+
const ruleId = finding.ruleId || "unknown";
|
|
399
|
+
if (!findingsByRule.has(ruleId)) {
|
|
400
|
+
findingsByRule.set(ruleId, []);
|
|
401
|
+
}
|
|
402
|
+
findingsByRule.get(ruleId).push(finding);
|
|
403
|
+
}
|
|
404
|
+
// Print errors
|
|
405
|
+
const errorFindings = result.findings.filter(f => f.level === "error");
|
|
406
|
+
if (errorFindings.length > 0) {
|
|
407
|
+
console.log(`\n${console_chars_1.emoji.error} Errors (blocking):`);
|
|
408
|
+
const errorsByRule = new Map();
|
|
409
|
+
for (const finding of errorFindings) {
|
|
410
|
+
const ruleId = finding.ruleId || "unknown";
|
|
411
|
+
if (!errorsByRule.has(ruleId)) {
|
|
412
|
+
errorsByRule.set(ruleId, []);
|
|
413
|
+
}
|
|
414
|
+
errorsByRule.get(ruleId).push(finding);
|
|
415
|
+
}
|
|
416
|
+
for (const [ruleId, ruleFindings] of errorsByRule) {
|
|
417
|
+
console.log(`\n ${ruleId} (${ruleFindings.length}):`);
|
|
418
|
+
for (const finding of ruleFindings.slice(0, 5)) {
|
|
419
|
+
console.log(` ${finding.file}:${finding.startLine}`);
|
|
420
|
+
console.log(` ${finding.message}`);
|
|
421
|
+
if (finding.suggestion) {
|
|
422
|
+
console.log(` ${console_chars_1.emoji.hint} ${finding.suggestion}`);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
if (ruleFindings.length > 5) {
|
|
426
|
+
console.log(` ... and ${ruleFindings.length - 5} more`);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
// Print warnings
|
|
431
|
+
const warningFindings = result.findings.filter(f => f.level === "warning");
|
|
432
|
+
if (warningFindings.length > 0) {
|
|
433
|
+
console.log(`\n${console_chars_1.emoji.warning} Warnings:`);
|
|
434
|
+
const warningsByRule = new Map();
|
|
435
|
+
for (const finding of warningFindings) {
|
|
436
|
+
const ruleId = finding.ruleId || "unknown";
|
|
437
|
+
if (!warningsByRule.has(ruleId)) {
|
|
438
|
+
warningsByRule.set(ruleId, []);
|
|
439
|
+
}
|
|
440
|
+
warningsByRule.get(ruleId).push(finding);
|
|
441
|
+
}
|
|
442
|
+
for (const [ruleId, ruleFindings] of warningsByRule) {
|
|
443
|
+
console.log(`\n ${ruleId} (${ruleFindings.length}):`);
|
|
444
|
+
for (const finding of ruleFindings.slice(0, 3)) {
|
|
445
|
+
console.log(` ${finding.file}:${finding.startLine}`);
|
|
446
|
+
console.log(` ${finding.message}`);
|
|
447
|
+
}
|
|
448
|
+
if (ruleFindings.length > 3) {
|
|
449
|
+
console.log(` ... and ${ruleFindings.length - 3} more`);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
console.log(`\n${console_chars_1.emoji.info} Accessibility Rules:`);
|
|
454
|
+
console.log(` - All images must have alt text`);
|
|
455
|
+
console.log(` - Form inputs need labels or aria-label`);
|
|
456
|
+
console.log(` - Buttons must have accessible text`);
|
|
457
|
+
console.log(` - onClick handlers need role & keyboard support`);
|
|
458
|
+
console.log(` - Heading levels should not skip`);
|
|
459
|
+
if (!result.passed) {
|
|
460
|
+
console.log(`\n${console_chars_1.emoji.error} ACCESSIBILITY VALIDATION FAILED`);
|
|
461
|
+
process.exit(1);
|
|
462
|
+
}
|
|
463
|
+
console.log(`\n${console_chars_1.emoji.warning} ACCESSIBILITY VALIDATION PASSED WITH WARNINGS`);
|
|
464
|
+
process.exit(0);
|
|
465
|
+
}
|
|
466
|
+
if (require.main === module) {
|
|
467
|
+
main().catch((err) => {
|
|
468
|
+
console.error(`${console_chars_1.emoji.error} Preflight failed:`, err);
|
|
469
|
+
process.exit(1);
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
//# sourceMappingURL=accessibility-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accessibility-validation.js","sourceRoot":"","sources":["../../../src/checks/accessibility/accessibility-validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { PreflightCheckResult } from "../../core/types";
|
|
3
|
+
export declare const id = "database/prisma-naming-conventions";
|
|
4
|
+
export declare const name = "Prisma Naming Conventions";
|
|
5
|
+
export declare const description = "Enforces consistent naming conventions in Prisma schema (@map directives, casing)";
|
|
6
|
+
export declare const category = "database";
|
|
7
|
+
export declare const blocking = true;
|
|
8
|
+
export declare const tags: string[];
|
|
9
|
+
export declare function run(): Promise<PreflightCheckResult>;
|
|
10
|
+
//# sourceMappingURL=prisma-naming-conventions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prisma-naming-conventions.d.ts","sourceRoot":"","sources":["../../../src/checks/database/prisma-naming-conventions.ts"],"names":[],"mappings":";AA0BA,OAAO,EAAE,oBAAoB,EAAoB,MAAM,kBAAkB,CAAC;AAG1E,eAAO,MAAM,EAAE,uCAAuC,CAAC;AACvD,eAAO,MAAM,IAAI,8BAA8B,CAAC;AAChD,eAAO,MAAM,WAAW,sFAAsF,CAAC;AAC/G,eAAO,MAAM,QAAQ,aAAa,CAAC;AACnC,eAAO,MAAM,QAAQ,OAAO,CAAC;AAC7B,eAAO,MAAM,IAAI,UAA4D,CAAC;AAqU9E,wBAAsB,GAAG,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAmCzD"}
|