real-prototypes-skill 0.1.0
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/.claude/skills/agent-browser-skill/SKILL.md +252 -0
- package/.claude/skills/real-prototypes-skill/.gitignore +188 -0
- package/.claude/skills/real-prototypes-skill/ACCESSIBILITY.md +668 -0
- package/.claude/skills/real-prototypes-skill/INSTALL.md +259 -0
- package/.claude/skills/real-prototypes-skill/LICENSE +21 -0
- package/.claude/skills/real-prototypes-skill/PUBLISH.md +310 -0
- package/.claude/skills/real-prototypes-skill/QUICKSTART.md +240 -0
- package/.claude/skills/real-prototypes-skill/README.md +442 -0
- package/.claude/skills/real-prototypes-skill/SKILL.md +375 -0
- package/.claude/skills/real-prototypes-skill/capture/capture-engine.js +1153 -0
- package/.claude/skills/real-prototypes-skill/capture/config.schema.json +170 -0
- package/.claude/skills/real-prototypes-skill/cli.js +596 -0
- package/.claude/skills/real-prototypes-skill/docs/TROUBLESHOOTING.md +278 -0
- package/.claude/skills/real-prototypes-skill/docs/schemas/capture-config.md +167 -0
- package/.claude/skills/real-prototypes-skill/docs/schemas/design-tokens.md +183 -0
- package/.claude/skills/real-prototypes-skill/docs/schemas/manifest.md +169 -0
- package/.claude/skills/real-prototypes-skill/examples/CLAUDE.md.example +73 -0
- package/.claude/skills/real-prototypes-skill/examples/amazon-chatbot/CLAUDE.md +136 -0
- package/.claude/skills/real-prototypes-skill/examples/amazon-chatbot/FEATURES.md +222 -0
- package/.claude/skills/real-prototypes-skill/examples/amazon-chatbot/README.md +82 -0
- package/.claude/skills/real-prototypes-skill/examples/amazon-chatbot/references/design-tokens.json +87 -0
- package/.claude/skills/real-prototypes-skill/examples/amazon-chatbot/references/screenshots/homepage-viewport.png +0 -0
- package/.claude/skills/real-prototypes-skill/examples/amazon-chatbot/references/screenshots/prototype-chatbot-final.png +0 -0
- package/.claude/skills/real-prototypes-skill/examples/amazon-chatbot/references/screenshots/prototype-fullpage-v2.png +0 -0
- package/.claude/skills/real-prototypes-skill/references/accessibility-fixes.md +298 -0
- package/.claude/skills/real-prototypes-skill/references/accessibility-report.json +253 -0
- package/.claude/skills/real-prototypes-skill/scripts/CAPTURE-ENHANCEMENTS.md +344 -0
- package/.claude/skills/real-prototypes-skill/scripts/IMPLEMENTATION-SUMMARY.md +517 -0
- package/.claude/skills/real-prototypes-skill/scripts/QUICK-START.md +229 -0
- package/.claude/skills/real-prototypes-skill/scripts/QUICKSTART-layout-analysis.md +148 -0
- package/.claude/skills/real-prototypes-skill/scripts/README-analyze-layout.md +407 -0
- package/.claude/skills/real-prototypes-skill/scripts/analyze-layout.js +880 -0
- package/.claude/skills/real-prototypes-skill/scripts/capture-platform.js +203 -0
- package/.claude/skills/real-prototypes-skill/scripts/comprehensive-capture.js +597 -0
- package/.claude/skills/real-prototypes-skill/scripts/create-manifest.js +338 -0
- package/.claude/skills/real-prototypes-skill/scripts/enterprise-pipeline.js +428 -0
- package/.claude/skills/real-prototypes-skill/scripts/extract-tokens.js +468 -0
- package/.claude/skills/real-prototypes-skill/scripts/full-site-capture.js +738 -0
- package/.claude/skills/real-prototypes-skill/scripts/generate-tailwind-config.js +296 -0
- package/.claude/skills/real-prototypes-skill/scripts/integrate-accessibility.sh +161 -0
- package/.claude/skills/real-prototypes-skill/scripts/manifest-schema.json +302 -0
- package/.claude/skills/real-prototypes-skill/scripts/setup-prototype.sh +167 -0
- package/.claude/skills/real-prototypes-skill/scripts/test-analyze-layout.js +338 -0
- package/.claude/skills/real-prototypes-skill/scripts/test-validation.js +307 -0
- package/.claude/skills/real-prototypes-skill/scripts/validate-accessibility.js +598 -0
- package/.claude/skills/real-prototypes-skill/scripts/validate-manifest.js +499 -0
- package/.claude/skills/real-prototypes-skill/scripts/validate-output.js +361 -0
- package/.claude/skills/real-prototypes-skill/scripts/validate-prerequisites.js +319 -0
- package/.claude/skills/real-prototypes-skill/scripts/verify-layout-analysis.sh +77 -0
- package/.claude/skills/real-prototypes-skill/templates/dashboard-widget.tsx.template +91 -0
- package/.claude/skills/real-prototypes-skill/templates/data-table.tsx.template +193 -0
- package/.claude/skills/real-prototypes-skill/templates/form-section.tsx.template +250 -0
- package/.claude/skills/real-prototypes-skill/templates/modal-dialog.tsx.template +239 -0
- package/.claude/skills/real-prototypes-skill/templates/nav-item.tsx.template +265 -0
- package/.claude/skills/real-prototypes-skill/validation/validation-engine.js +559 -0
- package/.env.example +74 -0
- package/LICENSE +21 -0
- package/README.md +444 -0
- package/bin/cli.js +319 -0
- package/package.json +59 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tailwind Config Generator
|
|
5
|
+
*
|
|
6
|
+
* Takes design tokens JSON (from extract-tokens.js) and generates
|
|
7
|
+
* a Tailwind CSS configuration extend section.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* node generate-tailwind-config.js <tokens.json>
|
|
11
|
+
* node extract-tokens.js index.html | node generate-tailwind-config.js
|
|
12
|
+
*
|
|
13
|
+
* Output: TypeScript tailwind.config.ts extend section
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Convert color name to Tailwind-friendly key
|
|
21
|
+
*/
|
|
22
|
+
function normalizeKey(key) {
|
|
23
|
+
return key
|
|
24
|
+
.replace(/([A-Z])/g, '-$1')
|
|
25
|
+
.toLowerCase()
|
|
26
|
+
.replace(/^-/, '')
|
|
27
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
28
|
+
.replace(/-+/g, '-');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Generate Tailwind colors configuration
|
|
33
|
+
*/
|
|
34
|
+
function generateColors(colors) {
|
|
35
|
+
const result = {};
|
|
36
|
+
|
|
37
|
+
Object.entries(colors).forEach(([key, value]) => {
|
|
38
|
+
const normalizedKey = normalizeKey(key);
|
|
39
|
+
result[normalizedKey] = value;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Generate Tailwind font family configuration
|
|
47
|
+
*/
|
|
48
|
+
function generateFontFamily(fonts) {
|
|
49
|
+
const result = {};
|
|
50
|
+
|
|
51
|
+
Object.entries(fonts).forEach(([key, value]) => {
|
|
52
|
+
const normalizedKey = normalizeKey(key);
|
|
53
|
+
// Wrap font name properly for Tailwind
|
|
54
|
+
result[normalizedKey] = [value, 'sans-serif'];
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Generate Tailwind font size configuration
|
|
62
|
+
*/
|
|
63
|
+
function generateFontSize(fontSizes) {
|
|
64
|
+
const result = {};
|
|
65
|
+
|
|
66
|
+
Object.entries(fontSizes).forEach(([key, value]) => {
|
|
67
|
+
result[key] = value;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Generate Tailwind spacing configuration
|
|
75
|
+
*/
|
|
76
|
+
function generateSpacing(spacing) {
|
|
77
|
+
const result = {};
|
|
78
|
+
|
|
79
|
+
Object.entries(spacing).forEach(([key, value]) => {
|
|
80
|
+
result[key] = value;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Generate Tailwind border radius configuration
|
|
88
|
+
*/
|
|
89
|
+
function generateBorderRadius(borderRadius) {
|
|
90
|
+
const result = {};
|
|
91
|
+
|
|
92
|
+
Object.entries(borderRadius).forEach(([key, value]) => {
|
|
93
|
+
result[key] = value;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Generate the full Tailwind config extend section
|
|
101
|
+
*/
|
|
102
|
+
function generateTailwindConfig(tokens) {
|
|
103
|
+
const config = {
|
|
104
|
+
colors: generateColors(tokens.colors || {}),
|
|
105
|
+
fontFamily: generateFontFamily(tokens.fonts || {}),
|
|
106
|
+
fontSize: generateFontSize(tokens.fontSizes || {}),
|
|
107
|
+
spacing: generateSpacing(tokens.spacing || {}),
|
|
108
|
+
borderRadius: generateBorderRadius(tokens.borderRadius || {})
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Remove empty objects
|
|
112
|
+
Object.keys(config).forEach(key => {
|
|
113
|
+
if (Object.keys(config[key]).length === 0) {
|
|
114
|
+
delete config[key];
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return config;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Format the config as TypeScript
|
|
123
|
+
*/
|
|
124
|
+
function formatAsTypeScript(config) {
|
|
125
|
+
const lines = [
|
|
126
|
+
'// Generated Tailwind CSS configuration',
|
|
127
|
+
'// Add this to your tailwind.config.ts in the theme.extend section',
|
|
128
|
+
'',
|
|
129
|
+
'import type { Config } from "tailwindcss";',
|
|
130
|
+
'',
|
|
131
|
+
'const config: Config = {',
|
|
132
|
+
' content: [',
|
|
133
|
+
' "./src/**/*.{js,ts,jsx,tsx,mdx}",',
|
|
134
|
+
' "./app/**/*.{js,ts,jsx,tsx,mdx}",',
|
|
135
|
+
' "./components/**/*.{js,ts,jsx,tsx,mdx}",',
|
|
136
|
+
' ],',
|
|
137
|
+
' theme: {',
|
|
138
|
+
' extend: {'
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
// Add colors
|
|
142
|
+
if (config.colors && Object.keys(config.colors).length > 0) {
|
|
143
|
+
lines.push(' colors: {');
|
|
144
|
+
Object.entries(config.colors).forEach(([key, value]) => {
|
|
145
|
+
lines.push(` "${key}": "${value}",`);
|
|
146
|
+
});
|
|
147
|
+
lines.push(' },');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Add font families
|
|
151
|
+
if (config.fontFamily && Object.keys(config.fontFamily).length > 0) {
|
|
152
|
+
lines.push(' fontFamily: {');
|
|
153
|
+
Object.entries(config.fontFamily).forEach(([key, value]) => {
|
|
154
|
+
const fontList = Array.isArray(value) ? value : [value];
|
|
155
|
+
lines.push(` "${key}": ${JSON.stringify(fontList)},`);
|
|
156
|
+
});
|
|
157
|
+
lines.push(' },');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Add font sizes
|
|
161
|
+
if (config.fontSize && Object.keys(config.fontSize).length > 0) {
|
|
162
|
+
lines.push(' fontSize: {');
|
|
163
|
+
Object.entries(config.fontSize).forEach(([key, value]) => {
|
|
164
|
+
lines.push(` "${key}": "${value}",`);
|
|
165
|
+
});
|
|
166
|
+
lines.push(' },');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Add spacing
|
|
170
|
+
if (config.spacing && Object.keys(config.spacing).length > 0) {
|
|
171
|
+
lines.push(' spacing: {');
|
|
172
|
+
Object.entries(config.spacing).forEach(([key, value]) => {
|
|
173
|
+
lines.push(` "${key}": "${value}",`);
|
|
174
|
+
});
|
|
175
|
+
lines.push(' },');
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Add border radius
|
|
179
|
+
if (config.borderRadius && Object.keys(config.borderRadius).length > 0) {
|
|
180
|
+
lines.push(' borderRadius: {');
|
|
181
|
+
Object.entries(config.borderRadius).forEach(([key, value]) => {
|
|
182
|
+
lines.push(` "${key}": "${value}",`);
|
|
183
|
+
});
|
|
184
|
+
lines.push(' },');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
lines.push(' },');
|
|
188
|
+
lines.push(' },');
|
|
189
|
+
lines.push(' plugins: [],');
|
|
190
|
+
lines.push('};');
|
|
191
|
+
lines.push('');
|
|
192
|
+
lines.push('export default config;');
|
|
193
|
+
|
|
194
|
+
return lines.join('\n');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Format just the extend section as JSON (for partial use)
|
|
199
|
+
*/
|
|
200
|
+
function formatAsExtendSection(config) {
|
|
201
|
+
return JSON.stringify(config, null, 2);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Read tokens from stdin or file
|
|
206
|
+
*/
|
|
207
|
+
async function readTokens(inputPath) {
|
|
208
|
+
if (inputPath) {
|
|
209
|
+
// Read from file
|
|
210
|
+
const resolvedPath = path.resolve(inputPath);
|
|
211
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
212
|
+
console.error(`Error: File not found: ${resolvedPath}`);
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
const content = fs.readFileSync(resolvedPath, 'utf8');
|
|
216
|
+
return JSON.parse(content);
|
|
217
|
+
} else {
|
|
218
|
+
// Read from stdin
|
|
219
|
+
return new Promise((resolve, reject) => {
|
|
220
|
+
let data = '';
|
|
221
|
+
process.stdin.setEncoding('utf8');
|
|
222
|
+
|
|
223
|
+
process.stdin.on('readable', () => {
|
|
224
|
+
let chunk;
|
|
225
|
+
while ((chunk = process.stdin.read()) !== null) {
|
|
226
|
+
data += chunk;
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
process.stdin.on('end', () => {
|
|
231
|
+
try {
|
|
232
|
+
resolve(JSON.parse(data));
|
|
233
|
+
} catch (err) {
|
|
234
|
+
reject(new Error('Invalid JSON input'));
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
process.stdin.on('error', reject);
|
|
239
|
+
|
|
240
|
+
// Set timeout for stdin
|
|
241
|
+
setTimeout(() => {
|
|
242
|
+
if (data === '') {
|
|
243
|
+
reject(new Error('No input received. Provide a file path or pipe JSON data.'));
|
|
244
|
+
}
|
|
245
|
+
}, 100);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// CLI execution
|
|
251
|
+
async function main() {
|
|
252
|
+
const args = process.argv.slice(2);
|
|
253
|
+
|
|
254
|
+
// Check for help flag
|
|
255
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
256
|
+
console.log('Usage: node generate-tailwind-config.js [options] [tokens.json]');
|
|
257
|
+
console.log('');
|
|
258
|
+
console.log('Generates Tailwind CSS configuration from design tokens.');
|
|
259
|
+
console.log('');
|
|
260
|
+
console.log('Arguments:');
|
|
261
|
+
console.log(' tokens.json Path to tokens JSON file (or pipe from stdin)');
|
|
262
|
+
console.log('');
|
|
263
|
+
console.log('Options:');
|
|
264
|
+
console.log(' --extend-only Output only the extend section as JSON');
|
|
265
|
+
console.log(' --help, -h Show this help message');
|
|
266
|
+
console.log('');
|
|
267
|
+
console.log('Examples:');
|
|
268
|
+
console.log(' node generate-tailwind-config.js tokens.json');
|
|
269
|
+
console.log(' node extract-tokens.js index.html | node generate-tailwind-config.js');
|
|
270
|
+
console.log(' node generate-tailwind-config.js tokens.json --extend-only');
|
|
271
|
+
process.exit(0);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const extendOnly = args.includes('--extend-only');
|
|
275
|
+
const inputPath = args.find(arg => !arg.startsWith('--'));
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
const tokens = await readTokens(inputPath);
|
|
279
|
+
const config = generateTailwindConfig(tokens);
|
|
280
|
+
|
|
281
|
+
if (extendOnly) {
|
|
282
|
+
console.log(formatAsExtendSection(config));
|
|
283
|
+
} else {
|
|
284
|
+
console.log(formatAsTypeScript(config));
|
|
285
|
+
}
|
|
286
|
+
} catch (err) {
|
|
287
|
+
console.error(`Error: ${err.message}`);
|
|
288
|
+
process.exit(1);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (require.main === module) {
|
|
293
|
+
main();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
module.exports = { generateTailwindConfig, formatAsTypeScript, formatAsExtendSection };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
###############################################################################
|
|
4
|
+
# Accessibility Integration Script
|
|
5
|
+
#
|
|
6
|
+
# Integrates accessibility validation into the prototype build process
|
|
7
|
+
# Installs dependencies, configures ESLint, and runs validation
|
|
8
|
+
###############################################################################
|
|
9
|
+
|
|
10
|
+
set -e
|
|
11
|
+
|
|
12
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)"
|
|
14
|
+
PROTOTYPE_DIR="$PROJECT_ROOT/prototype"
|
|
15
|
+
|
|
16
|
+
echo "=================================================="
|
|
17
|
+
echo "Accessibility Integration Script"
|
|
18
|
+
echo "=================================================="
|
|
19
|
+
echo ""
|
|
20
|
+
echo "Project Root: $PROJECT_ROOT"
|
|
21
|
+
echo "Prototype Dir: $PROTOTYPE_DIR"
|
|
22
|
+
echo ""
|
|
23
|
+
|
|
24
|
+
# Check if prototype directory exists
|
|
25
|
+
if [ ! -d "$PROTOTYPE_DIR" ]; then
|
|
26
|
+
echo "❌ Error: Prototype directory not found at $PROTOTYPE_DIR"
|
|
27
|
+
echo " Run setup-prototype.sh first to create the prototype project"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
cd "$PROTOTYPE_DIR"
|
|
32
|
+
|
|
33
|
+
# Step 1: Install accessibility dependencies
|
|
34
|
+
echo "📦 Installing accessibility dependencies..."
|
|
35
|
+
echo ""
|
|
36
|
+
|
|
37
|
+
if [ -f "package.json" ]; then
|
|
38
|
+
# Check if dependencies are already installed
|
|
39
|
+
if grep -q "eslint-plugin-jsx-a11y" package.json; then
|
|
40
|
+
echo "✅ Accessibility dependencies already in package.json"
|
|
41
|
+
else
|
|
42
|
+
echo "Adding dependencies to package.json..."
|
|
43
|
+
npm install --save-dev \
|
|
44
|
+
eslint@^8.57.0 \
|
|
45
|
+
eslint-config-next@^15.1.4 \
|
|
46
|
+
eslint-plugin-jsx-a11y@^6.10.2
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Ensure dependencies are installed
|
|
50
|
+
npm install
|
|
51
|
+
echo "✅ Dependencies installed"
|
|
52
|
+
else
|
|
53
|
+
echo "❌ Error: package.json not found"
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
echo ""
|
|
58
|
+
|
|
59
|
+
# Step 2: Create/update ESLint configuration
|
|
60
|
+
echo "🔧 Configuring ESLint for accessibility..."
|
|
61
|
+
echo ""
|
|
62
|
+
|
|
63
|
+
ESLINT_CONFIG="$PROTOTYPE_DIR/.eslintrc.json"
|
|
64
|
+
|
|
65
|
+
if [ -f "$ESLINT_CONFIG" ]; then
|
|
66
|
+
echo "✅ ESLint config already exists at $ESLINT_CONFIG"
|
|
67
|
+
else
|
|
68
|
+
echo "Creating ESLint configuration..."
|
|
69
|
+
cp "$SCRIPT_DIR/../.eslintrc.json.template" "$ESLINT_CONFIG" 2>/dev/null || {
|
|
70
|
+
echo "Template not found, using built-in config..."
|
|
71
|
+
cat > "$ESLINT_CONFIG" <<'EOF'
|
|
72
|
+
{
|
|
73
|
+
"extends": [
|
|
74
|
+
"next/core-web-vitals",
|
|
75
|
+
"plugin:jsx-a11y/recommended"
|
|
76
|
+
],
|
|
77
|
+
"plugins": ["jsx-a11y"],
|
|
78
|
+
"rules": {
|
|
79
|
+
"jsx-a11y/alt-text": "error",
|
|
80
|
+
"jsx-a11y/anchor-has-content": "error",
|
|
81
|
+
"jsx-a11y/anchor-is-valid": "error",
|
|
82
|
+
"jsx-a11y/aria-props": "error",
|
|
83
|
+
"jsx-a11y/aria-role": "error",
|
|
84
|
+
"jsx-a11y/click-events-have-key-events": "error",
|
|
85
|
+
"jsx-a11y/heading-has-content": "error",
|
|
86
|
+
"jsx-a11y/interactive-supports-focus": "error",
|
|
87
|
+
"jsx-a11y/label-has-associated-control": "error",
|
|
88
|
+
"jsx-a11y/no-noninteractive-element-interactions": "error",
|
|
89
|
+
"jsx-a11y/role-has-required-aria-props": "error"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
EOF
|
|
93
|
+
}
|
|
94
|
+
echo "✅ ESLint config created"
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
echo ""
|
|
98
|
+
|
|
99
|
+
# Step 3: Update package.json scripts
|
|
100
|
+
echo "📝 Adding accessibility validation scripts..."
|
|
101
|
+
echo ""
|
|
102
|
+
|
|
103
|
+
if grep -q "validate:a11y" package.json; then
|
|
104
|
+
echo "✅ Validation scripts already in package.json"
|
|
105
|
+
else
|
|
106
|
+
# Add scripts using node
|
|
107
|
+
node -e "
|
|
108
|
+
const fs = require('fs');
|
|
109
|
+
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
|
110
|
+
pkg.scripts = pkg.scripts || {};
|
|
111
|
+
pkg.scripts['lint:a11y'] = 'eslint . --ext .ts,.tsx,.js,.jsx';
|
|
112
|
+
pkg.scripts['validate:a11y'] = 'node ../.claude/skills/real-prototypes-skill/scripts/validate-accessibility.js . --verbose';
|
|
113
|
+
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2));
|
|
114
|
+
"
|
|
115
|
+
echo "✅ Scripts added to package.json"
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
echo ""
|
|
119
|
+
|
|
120
|
+
# Step 4: Create references directory if needed
|
|
121
|
+
echo "📁 Ensuring references directory exists..."
|
|
122
|
+
echo ""
|
|
123
|
+
|
|
124
|
+
REFERENCES_DIR="$PROJECT_ROOT/references"
|
|
125
|
+
if [ ! -d "$REFERENCES_DIR" ]; then
|
|
126
|
+
mkdir -p "$REFERENCES_DIR"
|
|
127
|
+
echo "✅ Created references directory"
|
|
128
|
+
else
|
|
129
|
+
echo "✅ References directory exists"
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
echo ""
|
|
133
|
+
|
|
134
|
+
# Step 5: Run initial validation
|
|
135
|
+
echo "🔍 Running initial accessibility validation..."
|
|
136
|
+
echo ""
|
|
137
|
+
|
|
138
|
+
node "$SCRIPT_DIR/validate-accessibility.js" "$PROTOTYPE_DIR" --verbose
|
|
139
|
+
|
|
140
|
+
echo ""
|
|
141
|
+
echo "=================================================="
|
|
142
|
+
echo "✅ Accessibility Integration Complete!"
|
|
143
|
+
echo "=================================================="
|
|
144
|
+
echo ""
|
|
145
|
+
echo "Next steps:"
|
|
146
|
+
echo ""
|
|
147
|
+
echo "1. Review the accessibility report:"
|
|
148
|
+
echo " → $REFERENCES_DIR/accessibility-report.json"
|
|
149
|
+
echo ""
|
|
150
|
+
echo "2. Review fixes documentation:"
|
|
151
|
+
echo " → $REFERENCES_DIR/accessibility-fixes.md"
|
|
152
|
+
echo ""
|
|
153
|
+
echo "3. Run validation anytime:"
|
|
154
|
+
echo " → npm run validate:a11y"
|
|
155
|
+
echo ""
|
|
156
|
+
echo "4. Run ESLint for accessibility:"
|
|
157
|
+
echo " → npm run lint:a11y"
|
|
158
|
+
echo ""
|
|
159
|
+
echo "5. Fix any issues found and re-run validation"
|
|
160
|
+
echo ""
|
|
161
|
+
echo "=================================================="
|