design-clone 1.2.0 → 2.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/README.md +26 -12
- package/bin/commands/clone-site.js +75 -10
- package/bin/commands/init.js +33 -1
- package/bin/commands/verify.js +5 -3
- package/bin/utils/validate.js +24 -8
- package/docs/cli-reference.md +200 -2
- package/docs/codebase-summary.md +309 -0
- package/docs/design-clone-architecture.md +259 -42
- package/docs/pixel-perfect.md +35 -4
- package/docs/project-roadmap.md +382 -0
- package/docs/troubleshooting.md +5 -4
- package/package.json +10 -8
- package/src/ai/__pycache__/analyze-structure.cpython-313.pyc +0 -0
- package/src/ai/__pycache__/extract-design-tokens.cpython-313.pyc +0 -0
- package/src/ai/analyze-structure.py +73 -3
- package/src/ai/extract-design-tokens.py +356 -13
- package/src/ai/prompts/__pycache__/design_tokens.cpython-313.pyc +0 -0
- package/src/ai/prompts/__pycache__/structure_analysis.cpython-313.pyc +0 -0
- package/src/ai/prompts/__pycache__/ux_audit.cpython-313.pyc +0 -0
- package/src/ai/prompts/design_tokens.py +133 -0
- package/src/ai/prompts/structure_analysis.py +329 -10
- package/src/ai/prompts/ux_audit.py +198 -0
- package/src/ai/ux-audit.js +596 -0
- package/src/core/app-state-snapshot.js +511 -0
- package/src/core/content-counter.js +342 -0
- package/src/core/cookie-handler.js +1 -1
- package/src/core/css-extractor.js +4 -4
- package/src/core/dimension-extractor.js +93 -21
- package/src/core/dimension-output.js +103 -6
- package/src/core/discover-pages.js +242 -14
- package/src/core/dom-tree-analyzer.js +298 -0
- package/src/core/extract-assets.js +1 -1
- package/src/core/framework-detector.js +538 -0
- package/src/core/html-extractor.js +45 -4
- package/src/core/lazy-loader.js +7 -7
- package/src/core/multi-page-screenshot.js +9 -6
- package/src/core/page-readiness.js +8 -8
- package/src/core/screenshot.js +138 -9
- package/src/core/section-cropper.js +209 -0
- package/src/core/section-detector.js +386 -0
- package/src/core/semantic-enhancer.js +492 -0
- package/src/core/state-capture.js +18 -22
- package/src/core/tests/test-section-cropper.js +177 -0
- package/src/core/tests/test-section-detector.js +55 -0
- package/src/core/video-capture.js +152 -146
- package/src/route-discoverers/angular-discoverer.js +157 -0
- package/src/route-discoverers/astro-discoverer.js +123 -0
- package/src/route-discoverers/base-discoverer.js +242 -0
- package/src/route-discoverers/index.js +106 -0
- package/src/route-discoverers/next-discoverer.js +130 -0
- package/src/route-discoverers/nuxt-discoverer.js +138 -0
- package/src/route-discoverers/react-discoverer.js +139 -0
- package/src/route-discoverers/svelte-discoverer.js +109 -0
- package/src/route-discoverers/universal-discoverer.js +227 -0
- package/src/route-discoverers/vue-discoverer.js +118 -0
- package/src/utils/__init__.py +1 -1
- package/src/utils/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/utils/browser.js +11 -37
- package/src/utils/playwright.js +213 -0
- package/src/verification/generate-audit-report.js +398 -0
- package/src/verification/verify-footer.js +493 -0
- package/src/verification/verify-header.js +486 -0
- package/src/verification/verify-layout.js +2 -2
- package/src/verification/verify-menu.js +4 -20
- package/src/verification/verify-slider.js +533 -0
- package/src/utils/puppeteer.js +0 -281
package/README.md
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Clone
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="logo.svg" alt="design-clone" width="120" height="120">
|
|
3
|
+
<h1>Design Clone</h1>
|
|
4
|
+
<p><strong>Clone website designs with multi-viewport screenshots, HTML/CSS extraction, and Gemini AI analysis.</strong></p>
|
|
5
|
+
<p>
|
|
6
|
+
<a href="https://www.npmjs.com/package/design-clone"><img src="https://img.shields.io/npm/v/design-clone" alt="npm"></a>
|
|
7
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
|
|
8
|
+
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg" alt="Node"></a>
|
|
9
|
+
</p>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
---
|
|
8
13
|
|
|
9
14
|
## Features
|
|
10
15
|
|
|
@@ -112,7 +117,7 @@ Get your API key at: https://aistudio.google.com/apikey
|
|
|
112
117
|
|
|
113
118
|
- Node.js 18+
|
|
114
119
|
- Python 3.9+ (for AI analysis)
|
|
115
|
-
-
|
|
120
|
+
- Playwright (auto-installed with browsers)
|
|
116
121
|
|
|
117
122
|
## CLI Commands
|
|
118
123
|
|
|
@@ -145,14 +150,17 @@ pip install google-genai
|
|
|
145
150
|
pip3 install -r requirements.txt
|
|
146
151
|
```
|
|
147
152
|
|
|
148
|
-
###
|
|
153
|
+
### Playwright issues
|
|
149
154
|
|
|
150
155
|
```bash
|
|
151
|
-
# Install
|
|
152
|
-
npm install
|
|
156
|
+
# Install Playwright if not present
|
|
157
|
+
npm install playwright
|
|
158
|
+
|
|
159
|
+
# Install browsers
|
|
160
|
+
npx playwright install chromium
|
|
153
161
|
|
|
154
162
|
# For Docker/CI environments
|
|
155
|
-
export
|
|
163
|
+
export PLAYWRIGHT_BROWSERS_PATH=/tmp/pw-browsers
|
|
156
164
|
```
|
|
157
165
|
|
|
158
166
|
See full troubleshooting guide: [docs/troubleshooting.md](docs/troubleshooting.md)
|
|
@@ -172,3 +180,9 @@ MIT - See [LICENSE](LICENSE)
|
|
|
172
180
|
## Credits
|
|
173
181
|
|
|
174
182
|
Built for use with [Claude Code](https://claude.ai/code) by Anthropic.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
<div align="center">
|
|
187
|
+
<sub>Made with ❤️ for the Claude Code community</sub>
|
|
188
|
+
</div>
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* --viewports <list> Viewport list (default: desktop,tablet,mobile)
|
|
13
13
|
* --yes Skip confirmation prompt
|
|
14
14
|
* --output <dir> Custom output directory
|
|
15
|
+
* --ux-audit Run UX audit using Gemini Vision (requires GEMINI_API_KEY)
|
|
15
16
|
*/
|
|
16
17
|
|
|
17
18
|
import fs from 'fs/promises';
|
|
@@ -23,6 +24,7 @@ import { captureMultiplePages } from '../../src/core/multi-page-screenshot.js';
|
|
|
23
24
|
import { mergeCssFiles } from '../../src/core/merge-css.js';
|
|
24
25
|
import { rewriteLinks, createPageManifest, rewriteAllLinks } from '../../src/core/rewrite-links.js';
|
|
25
26
|
import { extractDesignTokens } from '../../src/core/design-tokens.js';
|
|
27
|
+
import { runUXAudit } from '../../src/ai/ux-audit.js';
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
30
|
* Generate output directory name
|
|
@@ -53,7 +55,8 @@ export function parseArgs(args) {
|
|
|
53
55
|
viewports: ['desktop', 'tablet', 'mobile'],
|
|
54
56
|
skipConfirm: false,
|
|
55
57
|
output: null,
|
|
56
|
-
ai: false
|
|
58
|
+
ai: false,
|
|
59
|
+
uxAudit: false
|
|
57
60
|
};
|
|
58
61
|
|
|
59
62
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -71,6 +74,8 @@ export function parseArgs(args) {
|
|
|
71
74
|
options.output = args[++i];
|
|
72
75
|
} else if (arg === '--ai') {
|
|
73
76
|
options.ai = true;
|
|
77
|
+
} else if (arg === '--ux-audit') {
|
|
78
|
+
options.uxAudit = true;
|
|
74
79
|
} else if (!arg.startsWith('--') && !options.url) {
|
|
75
80
|
options.url = arg;
|
|
76
81
|
}
|
|
@@ -93,7 +98,8 @@ export async function cloneSite(url, options = {}) {
|
|
|
93
98
|
viewports = ['desktop', 'tablet', 'mobile'],
|
|
94
99
|
skipConfirm = false,
|
|
95
100
|
output,
|
|
96
|
-
ai = false
|
|
101
|
+
ai = false,
|
|
102
|
+
uxAudit = false
|
|
97
103
|
} = options;
|
|
98
104
|
|
|
99
105
|
// Validate URL
|
|
@@ -111,7 +117,7 @@ export async function cloneSite(url, options = {}) {
|
|
|
111
117
|
console.error(`[clone-site] Output: ${outputDir}`);
|
|
112
118
|
|
|
113
119
|
// Step 1: Discover or use manual pages
|
|
114
|
-
console.error('\n[1/
|
|
120
|
+
console.error('\n[1/7] Discovering pages...');
|
|
115
121
|
|
|
116
122
|
let pageList;
|
|
117
123
|
if (manualPages && manualPages.length > 0) {
|
|
@@ -141,7 +147,7 @@ export async function cloneSite(url, options = {}) {
|
|
|
141
147
|
}
|
|
142
148
|
|
|
143
149
|
// Step 2: Capture all pages
|
|
144
|
-
console.error('\n[2/
|
|
150
|
+
console.error('\n[2/7] Capturing pages...');
|
|
145
151
|
|
|
146
152
|
const captureResult = await captureMultiplePages(pageList.pages, {
|
|
147
153
|
outputDir,
|
|
@@ -159,7 +165,7 @@ export async function cloneSite(url, options = {}) {
|
|
|
159
165
|
console.error(` Screenshots: ${captureResult.stats.totalScreenshots}`);
|
|
160
166
|
|
|
161
167
|
// Step 3: Merge CSS files (prefer filtered CSS)
|
|
162
|
-
console.error('\n[3/
|
|
168
|
+
console.error('\n[3/7] Merging CSS...');
|
|
163
169
|
|
|
164
170
|
const mergedCssPath = path.join(outputDir, 'styles.css');
|
|
165
171
|
let mergeResult = { success: false };
|
|
@@ -184,7 +190,7 @@ export async function cloneSite(url, options = {}) {
|
|
|
184
190
|
}
|
|
185
191
|
|
|
186
192
|
// Step 4: Extract design tokens (if --ai flag)
|
|
187
|
-
console.error('\n[4/
|
|
193
|
+
console.error('\n[4/7] Extracting design tokens...');
|
|
188
194
|
|
|
189
195
|
let hasTokens = false;
|
|
190
196
|
if (ai) {
|
|
@@ -207,8 +213,64 @@ export async function cloneSite(url, options = {}) {
|
|
|
207
213
|
console.error(' Skipped (use --ai flag to enable)');
|
|
208
214
|
}
|
|
209
215
|
|
|
210
|
-
// Step 5:
|
|
211
|
-
console.error('\n[5/
|
|
216
|
+
// Step 5: UX Audit (if --ux-audit flag)
|
|
217
|
+
console.error('\n[5/7] Running UX audit...');
|
|
218
|
+
|
|
219
|
+
let uxAuditResult = null;
|
|
220
|
+
if (uxAudit) {
|
|
221
|
+
if (process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY) {
|
|
222
|
+
// Find homepage screenshots for audit
|
|
223
|
+
const screenshotDir = path.join(outputDir, 'screenshots');
|
|
224
|
+
const screenshotPaths = {};
|
|
225
|
+
|
|
226
|
+
for (const viewport of viewports) {
|
|
227
|
+
const screenshotPath = path.join(screenshotDir, `index-${viewport}.png`);
|
|
228
|
+
try {
|
|
229
|
+
await fs.access(screenshotPath);
|
|
230
|
+
screenshotPaths[viewport] = screenshotPath;
|
|
231
|
+
} catch {
|
|
232
|
+
// Try alternative naming
|
|
233
|
+
const altPath = path.join(screenshotDir, `${viewport}.png`);
|
|
234
|
+
try {
|
|
235
|
+
await fs.access(altPath);
|
|
236
|
+
screenshotPaths[viewport] = altPath;
|
|
237
|
+
} catch {
|
|
238
|
+
// Skip this viewport
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (Object.keys(screenshotPaths).length > 0) {
|
|
244
|
+
const analysisDir = path.join(outputDir, 'analysis');
|
|
245
|
+
await fs.mkdir(analysisDir, { recursive: true });
|
|
246
|
+
|
|
247
|
+
uxAuditResult = await runUXAudit(screenshotPaths, {
|
|
248
|
+
output: analysisDir,
|
|
249
|
+
verbose: true,
|
|
250
|
+
url
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
if (uxAuditResult.success) {
|
|
254
|
+
console.error(` UX Score: ${uxAuditResult.summary.uxScore}%`);
|
|
255
|
+
console.error(` Accessibility: ${uxAuditResult.summary.accessibilityScore}%`);
|
|
256
|
+
console.error(` Issues: ${uxAuditResult.summary.issueCount} (${uxAuditResult.summary.criticalCount} critical)`);
|
|
257
|
+
console.error(` Report: analysis/ux-audit.md`);
|
|
258
|
+
} else {
|
|
259
|
+
console.error(` Warning: UX audit failed - ${uxAuditResult.error}`);
|
|
260
|
+
}
|
|
261
|
+
} else {
|
|
262
|
+
console.error(' Skipped: No screenshots found for audit');
|
|
263
|
+
}
|
|
264
|
+
} else {
|
|
265
|
+
console.error(' Skipped: GEMINI_API_KEY not set');
|
|
266
|
+
console.error(' Hint: Set GEMINI_API_KEY in ~/.claude/.env for UX audit');
|
|
267
|
+
}
|
|
268
|
+
} else {
|
|
269
|
+
console.error(' Skipped (use --ux-audit flag to enable)');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Step 6: Rewrite links
|
|
273
|
+
console.error('\n[6/7] Rewriting links...');
|
|
212
274
|
|
|
213
275
|
const manifest = createPageManifest(pageList.pages, {
|
|
214
276
|
hasTokens,
|
|
@@ -241,8 +303,8 @@ export async function cloneSite(url, options = {}) {
|
|
|
241
303
|
}
|
|
242
304
|
}
|
|
243
305
|
|
|
244
|
-
// Step
|
|
245
|
-
console.error('\n[
|
|
306
|
+
// Step 7: Generate manifest
|
|
307
|
+
console.error('\n[7/7] Generating manifest...');
|
|
246
308
|
|
|
247
309
|
const manifestPath = path.join(outputDir, 'manifest.json');
|
|
248
310
|
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
@@ -261,6 +323,7 @@ export async function cloneSite(url, options = {}) {
|
|
|
261
323
|
manifest,
|
|
262
324
|
captureResult,
|
|
263
325
|
mergeResult,
|
|
326
|
+
uxAuditResult,
|
|
264
327
|
totalTimeMs: totalTime
|
|
265
328
|
};
|
|
266
329
|
}
|
|
@@ -281,12 +344,14 @@ Options:
|
|
|
281
344
|
--yes Skip confirmation prompt
|
|
282
345
|
--output <dir> Custom output directory
|
|
283
346
|
--ai Extract design tokens using Gemini AI (requires GEMINI_API_KEY)
|
|
347
|
+
--ux-audit Run UX audit using Gemini Vision (requires GEMINI_API_KEY)
|
|
284
348
|
|
|
285
349
|
Examples:
|
|
286
350
|
design-clone clone-site https://example.com
|
|
287
351
|
design-clone clone-site https://example.com --max-pages 5
|
|
288
352
|
design-clone clone-site https://example.com --pages /,/about,/contact
|
|
289
353
|
design-clone clone-site https://example.com --ai
|
|
354
|
+
design-clone clone-site https://example.com --ux-audit
|
|
290
355
|
`);
|
|
291
356
|
}
|
|
292
357
|
|
package/bin/commands/init.js
CHANGED
|
@@ -50,7 +50,7 @@ export async function init(args) {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
if (!checks.chrome.ok) {
|
|
53
|
-
console.warn('Warning: Chrome not found.
|
|
53
|
+
console.warn('Warning: Chrome not found. Playwright will download Chromium during installation.');
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// Check existing installation
|
|
@@ -129,6 +129,38 @@ export async function init(args) {
|
|
|
129
129
|
console.warn(` Warning: npm install failed: ${error.message}`);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
// Install Playwright
|
|
133
|
+
console.log('Installing Playwright...');
|
|
134
|
+
try {
|
|
135
|
+
// Check if playwright is already installed
|
|
136
|
+
let playwrightInstalled = false;
|
|
137
|
+
try {
|
|
138
|
+
await exec('node -e "require.resolve(\'playwright\')"', { cwd: SKILL_DEST });
|
|
139
|
+
playwrightInstalled = true;
|
|
140
|
+
console.log(' Playwright already installed');
|
|
141
|
+
} catch {
|
|
142
|
+
// Need to install
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (!playwrightInstalled) {
|
|
146
|
+
await exec('npm install playwright', { cwd: SKILL_DEST });
|
|
147
|
+
console.log(' Playwright installed');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Install Playwright browsers (chromium only for smaller footprint)
|
|
151
|
+
console.log('Installing Playwright browsers...');
|
|
152
|
+
try {
|
|
153
|
+
await exec('npx playwright install chromium', { cwd: SKILL_DEST, timeout: 300000 });
|
|
154
|
+
console.log(' Chromium browser installed');
|
|
155
|
+
} catch (browserError) {
|
|
156
|
+
console.warn(` Warning: Browser install failed: ${browserError.message}`);
|
|
157
|
+
console.warn(' Run manually: npx playwright install chromium');
|
|
158
|
+
}
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.warn(` Warning: Playwright install failed: ${error.message}`);
|
|
161
|
+
console.warn(' Run manually: npm install playwright && npx playwright install chromium');
|
|
162
|
+
}
|
|
163
|
+
|
|
132
164
|
// Python dependencies
|
|
133
165
|
if (checks.python.ok) {
|
|
134
166
|
console.log('Installing Python dependencies...');
|
package/bin/commands/verify.js
CHANGED
|
@@ -63,11 +63,13 @@ export async function verify() {
|
|
|
63
63
|
console.log('\nEnvironment:');
|
|
64
64
|
const checks = await runAllChecks();
|
|
65
65
|
|
|
66
|
-
console.log(` Node.js:
|
|
67
|
-
console.log(` Python:
|
|
68
|
-
console.log(`
|
|
66
|
+
console.log(` Node.js: ${checks.node.ok ? '✓' : '✗'} ${checks.node.message}`);
|
|
67
|
+
console.log(` Python: ${checks.python.ok ? '✓' : '✗'} ${checks.python.message}`);
|
|
68
|
+
console.log(` Playwright: ${checks.playwright.ok ? '✓' : '✗'} ${checks.playwright.message}`);
|
|
69
|
+
console.log(` Chrome: ${checks.chrome.ok ? '✓' : '○'} ${checks.chrome.message}${checks.playwright.ok ? ' (optional with Playwright)' : ''}`);
|
|
69
70
|
|
|
70
71
|
if (!checks.node.ok) allOk = false;
|
|
72
|
+
if (!checks.playwright.ok && !checks.chrome.ok) allOk = false;
|
|
71
73
|
|
|
72
74
|
// Check Gemini API key
|
|
73
75
|
console.log('\nOptional:');
|
package/bin/utils/validate.js
CHANGED
|
@@ -94,15 +94,31 @@ export async function checkChrome() {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
|
-
* Check
|
|
97
|
+
* Check Playwright
|
|
98
98
|
* @returns {Promise<{ok: boolean, message: string}>}
|
|
99
99
|
*/
|
|
100
|
-
export async function
|
|
100
|
+
export async function checkPlaywright() {
|
|
101
101
|
try {
|
|
102
|
-
await import('
|
|
103
|
-
|
|
102
|
+
const playwright = await import('playwright');
|
|
103
|
+
// Check if browsers are installed by checking chromium executable
|
|
104
|
+
if (playwright.chromium?.executablePath) {
|
|
105
|
+
try {
|
|
106
|
+
const fs = await import('fs/promises');
|
|
107
|
+
await fs.access(playwright.chromium.executablePath());
|
|
108
|
+
return { ok: true, message: 'Playwright installed with browsers' };
|
|
109
|
+
} catch {
|
|
110
|
+
return { ok: true, message: 'Playwright installed (browsers may need install)' };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return { ok: true, message: 'Playwright installed' };
|
|
104
114
|
} catch {
|
|
105
|
-
|
|
115
|
+
// Try playwright-core
|
|
116
|
+
try {
|
|
117
|
+
await import('playwright-core');
|
|
118
|
+
return { ok: true, message: 'playwright-core installed (needs Chrome)' };
|
|
119
|
+
} catch {
|
|
120
|
+
return { ok: false, message: 'Playwright not installed' };
|
|
121
|
+
}
|
|
106
122
|
}
|
|
107
123
|
}
|
|
108
124
|
|
|
@@ -111,12 +127,12 @@ export async function checkPuppeteer() {
|
|
|
111
127
|
* @returns {Promise<Object>}
|
|
112
128
|
*/
|
|
113
129
|
export async function runAllChecks() {
|
|
114
|
-
const [node, python, chrome,
|
|
130
|
+
const [node, python, chrome, playwright] = await Promise.all([
|
|
115
131
|
checkNode(),
|
|
116
132
|
checkPython(),
|
|
117
133
|
checkChrome(),
|
|
118
|
-
|
|
134
|
+
checkPlaywright()
|
|
119
135
|
]);
|
|
120
136
|
|
|
121
|
-
return { node, python, chrome,
|
|
137
|
+
return { node, python, chrome, playwright };
|
|
122
138
|
}
|
package/docs/cli-reference.md
CHANGED
|
@@ -25,11 +25,49 @@ node src/core/screenshot.js [options]
|
|
|
25
25
|
| --extract-animations | bool | true* | Extract @keyframes and transitions (enabled with --extract-css) |
|
|
26
26
|
| --filter-unused | bool | true | Filter CSS to remove unused selectors |
|
|
27
27
|
| --capture-hover | bool | false | Capture hover state screenshots and generate :hover CSS |
|
|
28
|
+
| --no-semantic | bool | false | Disable WordPress semantic HTML enhancement (Phase 3) |
|
|
28
29
|
| --verbose | bool | false | Verbose logging |
|
|
29
30
|
|
|
30
31
|
*Default true when --extract-css is enabled, can be disabled with `--extract-animations false`
|
|
31
32
|
|
|
32
|
-
**Output**: JSON with screenshot paths and metadata. Includes `browserRestarts` count tracking for stability monitoring. When `--capture-hover` is enabled, also includes hover state results in output.
|
|
33
|
+
**Output**: JSON with screenshot paths and metadata. Includes `browserRestarts` count tracking for stability monitoring. When `--capture-hover` is enabled, also includes hover state results in output. When semantic enhancement is enabled (default), output includes `semanticStats` with enhancement details (sections enhanced, IDs/classes/roles added).
|
|
34
|
+
|
|
35
|
+
### Semantic HTML Enhancement (Phase 3)
|
|
36
|
+
|
|
37
|
+
Semantic HTML enhancement is enabled by default when extracting HTML. It injects WordPress-compatible semantic IDs, classes, and ARIA roles into the extracted HTML.
|
|
38
|
+
|
|
39
|
+
**What's Added**:
|
|
40
|
+
- **IDs**: `site-header`, `main-content`, `site-footer`, `site-navigation`, `primary-sidebar`, `hero-section`
|
|
41
|
+
- **Classes**: `site-header`, `main-navigation`, `nav-menu`, `site-main`, `content-area`, `widget-area`, `sidebar`, `site-footer`, `hero`
|
|
42
|
+
- **ARIA Roles**: `banner` (header), `navigation` (nav), `main`, `complementary` (sidebar), `contentinfo` (footer)
|
|
43
|
+
|
|
44
|
+
**Detection Priority**:
|
|
45
|
+
1. Semantic HTML tags (`<header>`, `<nav>`, `<main>`, `<aside>`, `<footer>`)
|
|
46
|
+
2. ARIA role attributes (`banner`, `navigation`, `main`, `complementary`, `contentinfo`)
|
|
47
|
+
3. Class patterns (header, nav, main, sidebar, footer, hero)
|
|
48
|
+
|
|
49
|
+
**Usage**:
|
|
50
|
+
```bash
|
|
51
|
+
# Enable semantic enhancement (default)
|
|
52
|
+
node src/core/screenshot.js --url https://example.com --output ./out --extract-html
|
|
53
|
+
|
|
54
|
+
# Disable semantic enhancement
|
|
55
|
+
node src/core/screenshot.js --url https://example.com --output ./out --extract-html --no-semantic
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Example Output Metadata**:
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"html": "path/to/source.html",
|
|
62
|
+
"semanticStats": {
|
|
63
|
+
"sectionsEnhanced": 5,
|
|
64
|
+
"idsAdded": 3,
|
|
65
|
+
"classesAdded": 4,
|
|
66
|
+
"rolesAdded": 2,
|
|
67
|
+
"warnings": []
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
33
71
|
|
|
34
72
|
## filter-css.js
|
|
35
73
|
|
|
@@ -86,9 +124,62 @@ node src/core/extract-assets.js --url URL --output DIR
|
|
|
86
124
|
Validate navigation structure.
|
|
87
125
|
|
|
88
126
|
```bash
|
|
89
|
-
node src/verification/verify-menu.js --html FILE
|
|
127
|
+
node src/verification/verify-menu.js --html FILE [--url URL] [--output DIR] [--verbose]
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
| Option | Description |
|
|
131
|
+
|--------|-------------|
|
|
132
|
+
| --html | Path to HTML file |
|
|
133
|
+
| --url | URL to test (alternative to --html) |
|
|
134
|
+
| --output | Output directory for screenshots |
|
|
135
|
+
| --verbose | Show detailed progress |
|
|
136
|
+
|
|
137
|
+
## verify-header.js
|
|
138
|
+
|
|
139
|
+
Verify header components (Phase 1).
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
node src/verification/verify-header.js --html FILE [--url URL] [--output DIR] [--verbose]
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Tests: logo presence, navigation visibility, CTA buttons, sticky/fixed behavior, z-index layering, height consistency.
|
|
146
|
+
|
|
147
|
+
## verify-footer.js
|
|
148
|
+
|
|
149
|
+
Verify footer components (Phase 1).
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
node src/verification/verify-footer.js --html FILE [--url URL] [--output DIR] [--verbose]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Tests: position at bottom, multi-column layout, link sections, copyright text, social icons, background contrast.
|
|
156
|
+
|
|
157
|
+
## verify-slider.js
|
|
158
|
+
|
|
159
|
+
Verify slider/carousel components (Phase 1).
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
node src/verification/verify-slider.js --html FILE [--url URL] [--output DIR] [--verbose]
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Tests: library detection (Swiper, Slick, Owl, native), navigation arrows, pagination dots, autoplay behavior, current slide indicator.
|
|
166
|
+
|
|
167
|
+
## generate-audit-report.js
|
|
168
|
+
|
|
169
|
+
Aggregate verification results into consolidated report (Phase 1).
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
node src/verification/generate-audit-report.js --dir DIR [--output FILE] [--verbose]
|
|
90
173
|
```
|
|
91
174
|
|
|
175
|
+
| Option | Description |
|
|
176
|
+
|--------|-------------|
|
|
177
|
+
| --dir | Directory containing verification JSON results |
|
|
178
|
+
| --output | Output path for report (default: component-audit.md) |
|
|
179
|
+
| --verbose | Show detailed progress |
|
|
180
|
+
|
|
181
|
+
Output: Markdown report with summary table, side-by-side screenshots, responsive analysis, CSS suggestions.
|
|
182
|
+
|
|
92
183
|
## verify-layout.js
|
|
93
184
|
|
|
94
185
|
Verify layout consistency.
|
|
@@ -116,3 +207,110 @@ Used internally by screenshot.js with `--capture-hover` flag.
|
|
|
116
207
|
- Automatic screenshot pair generation (normal + hover states)
|
|
117
208
|
- CSS rule generation from detected style changes
|
|
118
209
|
- Validates selectors and skips hidden/invisible elements
|
|
210
|
+
|
|
211
|
+
## ux-audit.js
|
|
212
|
+
|
|
213
|
+
UX quality assessment using Gemini Vision AI (Phase 2).
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
node src/ai/ux-audit.js --screenshots <dir> [--output <dir>] [--url <url>] [--verbose]
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
| Option | Required | Description |
|
|
220
|
+
|--------|----------|-------------|
|
|
221
|
+
| --screenshots | yes | Directory containing viewport screenshots (desktop.png, tablet.png, mobile.png) |
|
|
222
|
+
| --output | no | Output directory for report and JSON results (default: same as screenshots) |
|
|
223
|
+
| --url | no | Original URL (for report metadata) |
|
|
224
|
+
| --verbose | no | Show detailed progress |
|
|
225
|
+
|
|
226
|
+
**Requires**: GEMINI_API_KEY or GOOGLE_API_KEY environment variable
|
|
227
|
+
|
|
228
|
+
**Output**:
|
|
229
|
+
- `ux-audit.md`: Markdown report with scores, issues, and recommendations
|
|
230
|
+
- `ux-audit.json`: Structured results (aggregated scores, viewport breakdown, issues, recommendations)
|
|
231
|
+
|
|
232
|
+
**Evaluation Categories** (0-100 score each):
|
|
233
|
+
1. Visual Hierarchy - Content prominence, scanning patterns, call-to-action visibility
|
|
234
|
+
2. Navigation - Touch targets, menu discoverability, current page indicator
|
|
235
|
+
3. Typography - Text size, line height, contrast ratio, readability
|
|
236
|
+
4. Spacing - Padding/margins, element breathing room, touch target spacing
|
|
237
|
+
5. Interactive Elements - Button affordance, link distinguishability, focus states
|
|
238
|
+
6. Responsive - Content reflow, no horizontal scroll, text truncation, breakpoint transitions
|
|
239
|
+
|
|
240
|
+
**Viewport Analysis**: Evaluates all three viewports (desktop: 1920×1080, tablet: 768×1024, mobile: 375×812) and generates weighted scores (desktop 40%, tablet 30%, mobile 30%).
|
|
241
|
+
|
|
242
|
+
**Issue Severity Levels**:
|
|
243
|
+
- Critical (0-30 score): Blocks tasks or causes confusion
|
|
244
|
+
- Major (31-60 score): Degrades experience significantly
|
|
245
|
+
- Minor (61-80 score): Polish improvements
|
|
246
|
+
|
|
247
|
+
**Scoring Scale**:
|
|
248
|
+
- 90-100: Excellent, industry-leading UX
|
|
249
|
+
- 70-89: Good, meets modern standards
|
|
250
|
+
- 50-69: Adequate, room for improvement
|
|
251
|
+
- 30-49: Poor, significant issues
|
|
252
|
+
- 0-29: Critical, requires immediate attention
|
|
253
|
+
|
|
254
|
+
## clone-site.js
|
|
255
|
+
|
|
256
|
+
Clone multiple pages from website with integrated UX audit (Phase 2).
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
design-clone clone-site <url> [options]
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
| Option | Description |
|
|
263
|
+
|--------|-------------|
|
|
264
|
+
| --pages <paths> | Comma-separated paths (e.g., /,/about,/contact) |
|
|
265
|
+
| --max-pages <n> | Maximum pages to auto-discover (default: 10) |
|
|
266
|
+
| --viewports <list> | Viewport list (default: desktop,tablet,mobile) |
|
|
267
|
+
| --output <dir> | Custom output directory |
|
|
268
|
+
| --ai | Extract design tokens using Gemini AI (requires GEMINI_API_KEY) |
|
|
269
|
+
| --ux-audit | Run UX audit using Gemini Vision (requires GEMINI_API_KEY) |
|
|
270
|
+
| --yes, -y | Skip confirmation prompt |
|
|
271
|
+
|
|
272
|
+
**Integrated Workflow** (when using --ux-audit):
|
|
273
|
+
1. Discover or use manual pages
|
|
274
|
+
2. Capture screenshots across viewports
|
|
275
|
+
3. Merge CSS files
|
|
276
|
+
4. Extract design tokens (with --ai)
|
|
277
|
+
5. **Run UX audit** (with --ux-audit) - Analyzes homepage screenshots via Gemini Vision
|
|
278
|
+
6. Rewrite links
|
|
279
|
+
7. Generate manifest
|
|
280
|
+
|
|
281
|
+
**UX Audit Output**: When enabled, generates `analysis/ux-audit.md` and `analysis/ux-audit.json` in output directory.
|
|
282
|
+
|
|
283
|
+
**Examples**:
|
|
284
|
+
```bash
|
|
285
|
+
design-clone clone-site https://example.com --ux-audit
|
|
286
|
+
design-clone clone-site https://example.com --pages /,/about,/contact --ux-audit
|
|
287
|
+
design-clone clone-site https://example.com --ai --ux-audit
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## ux_audit.py
|
|
291
|
+
|
|
292
|
+
Python module providing UX audit prompts for Gemini Vision integration.
|
|
293
|
+
|
|
294
|
+
```python
|
|
295
|
+
from src.ai.prompts.ux_audit import build_ux_audit_prompt, build_aggregation_prompt
|
|
296
|
+
|
|
297
|
+
# Build viewport-specific prompt
|
|
298
|
+
prompt = build_ux_audit_prompt(viewport='mobile')
|
|
299
|
+
|
|
300
|
+
# Build aggregation prompt for multiple viewports
|
|
301
|
+
aggregation = build_aggregation_prompt(desktop_results, tablet_results, mobile_results)
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**Functions**:
|
|
305
|
+
- `build_ux_audit_prompt(viewport)` - Build prompt with viewport-specific checks (mobile/tablet/desktop)
|
|
306
|
+
- `build_aggregation_prompt(desktop, tablet, mobile)` - Combine viewport results into unified assessment
|
|
307
|
+
|
|
308
|
+
**Constants**:
|
|
309
|
+
- `UX_AUDIT_PROMPT` - Base UX evaluation prompt (6 categories)
|
|
310
|
+
- `VIEWPORT_CONTEXT` - Dictionary of viewport-specific evaluation criteria
|
|
311
|
+
- `AGGREGATION_PROMPT` - Template for combining viewport results with weighted averaging
|
|
312
|
+
|
|
313
|
+
**Viewport Weighting**:
|
|
314
|
+
- Desktop: 40% (primary interaction model)
|
|
315
|
+
- Tablet: 30% (hybrid interaction)
|
|
316
|
+
- Mobile: 30% (touch-first)
|