MCPcopy Create free account
hub / github.com/SethGammon/Citadel / lensAccessibility

Function lensAccessibility

hooks_src/quality-gate.js:241–282  ·  view source on GitHub ↗
(file, content)

Source from the content-addressed store, hash-verified

239 if (/setInterval\s*\([^,]+,\s*\d+\s*\)/.test(content)) {
240 violations.push({ file, lens: 'performance', rule: 'no-magic-intervals', message: 'Hardcoded setInterval — use a named constant for the interval' });
241 }
242 }
243
244 return violations;
245}
246
247// ── Accessibility Lens ──────────────────────────────────────────────────────
248
249function lensAccessibility(file, content) {
250 if (!/\.(tsx|jsx)$/.test(file)) return [];
251
252 const violations = [];
253
254 // Check for onClick on non-button elements without role/tabIndex
255 const onClickDivRegex = /<(?:div|span|a(?!\s+href))\s[^>]*onClick[^>]*>/g;
256 let match;
257 while ((match = onClickDivRegex.exec(content)) !== null) {
258 const tag = match[0];
259 if (!tag.includes('role=') && !tag.includes('tabIndex')) {
260 violations.push({
261 file,
262 lens: 'accessibility',
263 message: 'Interactive element with onClick but missing role and tabIndex',
264 });
265 break; // One warning per file to avoid noise
266 }
267 }
268
269 // Check for img tags without alt attribute
270 const imgNoAlt = /<img\s(?![^>]*alt=)[^>]*>/;
271 if (imgNoAlt.test(content)) {
272 violations.push({
273 file,
274 lens: 'accessibility',
275 message: 'img element without alt attribute',
276 });
277 }
278
279 // Check for icon-only buttons without aria-label
280 const iconButtonRegex = /<button\s(?![^>]*aria-label)[^>]*>[\s]*<(?:svg|Icon|img)/;
281 if (iconButtonRegex.test(content)) {
282 violations.push({
283 file,
284 lens: 'accessibility',
285 message: 'Icon-only button without aria-label',

Callers 1

runColdLensFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected