design-clone 1.2.0 → 2.3.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 +32 -39
- package/SKILL.md +69 -45
- package/bin/cli.js +22 -4
- package/bin/commands/clone-site.js +31 -106
- package/bin/commands/help.js +19 -6
- package/bin/commands/init.js +11 -56
- package/bin/commands/uninstall.js +105 -0
- package/bin/commands/update.js +70 -0
- package/bin/commands/verify.js +11 -16
- package/bin/utils/paths.js +28 -0
- package/bin/utils/validate.js +24 -28
- package/bin/utils/version.js +23 -0
- package/docs/code-standards.md +789 -0
- package/docs/codebase-summary.md +556 -0
- package/docs/index.md +74 -0
- package/docs/project-overview-pdr.md +797 -0
- package/docs/system-architecture.md +718 -0
- package/package.json +20 -21
- package/src/ai/prompts/design-tokens/basic.md +80 -0
- package/src/ai/prompts/design-tokens/section-with-css.md +41 -0
- package/src/ai/prompts/design-tokens/section.md +48 -0
- package/src/ai/prompts/design-tokens/with-css.md +87 -0
- package/src/ai/prompts/structure-analysis/basic.md +55 -0
- package/src/ai/prompts/structure-analysis/with-context.md +59 -0
- package/src/ai/prompts/structure-analysis/with-dimensions.md +63 -0
- package/src/ai/prompts/structure-analysis/with-hierarchy.md +73 -0
- package/src/ai/prompts/ux-audit/aggregation.md +42 -0
- package/src/ai/prompts/ux-audit/desktop.md +92 -0
- package/src/ai/prompts/ux-audit/mobile.md +93 -0
- package/src/ai/prompts/ux-audit/tablet.md +92 -0
- package/src/core/animation/animation-extractor-ast.js +183 -0
- package/src/core/animation/animation-extractor-output.js +152 -0
- package/src/core/animation/animation-extractor.js +178 -0
- package/src/core/animation/state-capture-detection.js +200 -0
- package/src/core/animation/state-capture.js +193 -0
- package/src/core/capture/browser-context-pool.js +96 -0
- package/src/core/capture/multi-page-screenshot-page.js +110 -0
- package/src/core/capture/multi-page-screenshot.js +208 -0
- package/src/core/capture/screenshot-extraction.js +186 -0
- package/src/core/capture/screenshot-helpers.js +175 -0
- package/src/core/capture/screenshot-orchestrator.js +174 -0
- package/src/core/capture/screenshot-viewport.js +93 -0
- package/src/core/capture/screenshot.js +192 -0
- package/src/core/content/content-counter-dom.js +191 -0
- package/src/core/content/content-counter.js +76 -0
- package/src/core/css/breakpoint-detector.js +66 -0
- package/src/core/css/chromium-defaults.json +23 -0
- package/src/core/css/computed-style-extractor.js +102 -0
- package/src/core/css/css-chunker.js +103 -0
- package/src/core/{css-extractor.js → css/css-extractor.js} +4 -4
- package/src/core/css/filter-css-dead-code.js +120 -0
- package/src/core/css/filter-css-html-analyzer.js +110 -0
- package/src/core/css/filter-css-selector-matcher.js +172 -0
- package/src/core/css/filter-css.js +206 -0
- package/src/core/css/merge-css-atrule-processor.js +158 -0
- package/src/core/css/merge-css-file-io.js +68 -0
- package/src/core/css/merge-css.js +148 -0
- package/src/core/detection/framework-detector-routing.js +68 -0
- package/src/core/detection/framework-detector-signals.js +65 -0
- package/src/core/detection/framework-detector.js +198 -0
- package/src/core/dimension/dimension-extractor-card-detector.js +82 -0
- package/src/core/dimension/dimension-extractor.js +317 -0
- package/src/core/dimension/dimension-output-ai-summary.js +111 -0
- package/src/core/dimension/dimension-output.js +173 -0
- package/src/core/dimension/dom-tree-analyzer-tree-builders.js +95 -0
- package/src/core/dimension/dom-tree-analyzer.js +191 -0
- package/src/core/discovery/app-state-snapshot-capture.js +195 -0
- package/src/core/discovery/app-state-snapshot-utils.js +178 -0
- package/src/core/discovery/app-state-snapshot.js +131 -0
- package/src/core/discovery/discover-pages-routes.js +84 -0
- package/src/core/discovery/discover-pages-utils.js +177 -0
- package/src/core/discovery/discover-pages.js +191 -0
- package/src/core/html/html-extractor-inline-styler.js +70 -0
- package/src/core/html/html-extractor.js +147 -0
- package/src/core/html/semantic-enhancer-mappings.js +200 -0
- package/src/core/html/semantic-enhancer-page.js +148 -0
- package/src/core/html/semantic-enhancer.js +135 -0
- package/src/core/links/rewrite-links-css-rewriter.js +53 -0
- package/src/core/links/rewrite-links.js +173 -0
- package/src/core/media/asset-validator.js +118 -0
- package/src/core/media/extract-assets-downloader.js +187 -0
- package/src/core/media/extract-assets-page-scraper.js +115 -0
- package/src/core/media/extract-assets.js +159 -0
- package/src/core/media/video-capture-convert.js +200 -0
- package/src/core/media/video-capture.js +201 -0
- package/src/core/{cookie-handler.js → page-prep/cookie-handler.js} +1 -1
- package/src/core/{lazy-loader.js → page-prep/lazy-loader.js} +44 -46
- package/src/core/{page-readiness.js → page-prep/page-readiness.js} +8 -8
- package/src/core/section/section-cropper-helpers.js +43 -0
- package/src/core/section/section-cropper.js +132 -0
- package/src/core/section/section-detector-strategies.js +139 -0
- package/src/core/section/section-detector-utils.js +100 -0
- package/src/core/section/section-detector.js +88 -0
- package/src/core/tests/test-section-cropper.js +177 -0
- package/src/core/tests/test-section-detector.js +55 -0
- package/src/post-process/enhance-assets.js +29 -4
- package/src/post-process/fetch-images-unsplash-client.js +123 -0
- package/src/post-process/fetch-images.js +60 -263
- package/src/post-process/inject-gosnap.js +88 -0
- package/src/post-process/inject-icons-svg-replacer.js +76 -0
- package/src/post-process/inject-icons.js +47 -200
- package/src/route-discoverers/angular-discoverer.js +157 -0
- package/src/route-discoverers/astro-discoverer.js +123 -0
- package/src/route-discoverers/base-discoverer-utils.js +137 -0
- package/src/route-discoverers/base-discoverer.js +153 -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/shared/config.js +38 -0
- package/src/shared/error-codes.js +31 -0
- package/src/shared/viewports.js +46 -0
- package/src/utils/browser.js +11 -44
- package/src/utils/helpers.js +4 -0
- package/src/utils/log.js +12 -0
- package/src/utils/playwright-loader.js +76 -0
- package/src/utils/playwright.js +147 -0
- package/src/utils/progress.js +32 -0
- package/src/verification/generate-audit-report-css-fixes.js +52 -0
- package/src/verification/generate-audit-report-sections.js +158 -0
- package/src/verification/generate-audit-report.js +122 -0
- package/src/verification/quality-scorer.js +92 -0
- package/src/verification/verify-footer-checks.js +103 -0
- package/src/verification/verify-footer-helpers.js +178 -0
- package/src/verification/verify-footer.js +135 -0
- package/src/verification/verify-header-checks.js +104 -0
- package/src/verification/verify-header-helpers.js +156 -0
- package/src/verification/verify-header.js +144 -0
- package/src/verification/verify-layout-report.js +101 -0
- package/src/verification/verify-layout.js +14 -260
- package/src/verification/verify-menu-checks.js +104 -0
- package/src/verification/verify-menu-helpers.js +112 -0
- package/src/verification/verify-menu.js +18 -302
- package/src/verification/verify-slider-checks.js +115 -0
- package/src/verification/verify-slider-constants.js +65 -0
- package/src/verification/verify-slider-helpers.js +164 -0
- package/src/verification/verify-slider.js +142 -0
- package/.env.example +0 -14
- package/docs/basic-clone.md +0 -63
- package/docs/cli-reference.md +0 -118
- package/docs/design-clone-architecture.md +0 -275
- package/docs/pixel-perfect.md +0 -86
- package/docs/troubleshooting.md +0 -169
- package/requirements.txt +0 -5
- package/src/ai/analyze-structure.py +0 -305
- package/src/ai/extract-design-tokens.py +0 -439
- package/src/ai/prompts/__init__.py +0 -2
- package/src/ai/prompts/__pycache__/__init__.cpython-313.pyc +0 -0
- 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/design_tokens.py +0 -183
- package/src/ai/prompts/structure_analysis.py +0 -273
- package/src/core/animation-extractor.js +0 -526
- package/src/core/design-tokens.js +0 -103
- package/src/core/dimension-extractor.js +0 -366
- package/src/core/dimension-output.js +0 -208
- package/src/core/discover-pages.js +0 -314
- package/src/core/extract-assets.js +0 -468
- package/src/core/filter-css.js +0 -499
- package/src/core/html-extractor.js +0 -171
- package/src/core/merge-css.js +0 -407
- package/src/core/multi-page-screenshot.js +0 -377
- package/src/core/rewrite-links.js +0 -226
- package/src/core/screenshot.js +0 -572
- package/src/core/state-capture.js +0 -602
- package/src/core/video-capture.js +0 -540
- package/src/utils/__init__.py +0 -16
- package/src/utils/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/utils/__pycache__/env.cpython-313.pyc +0 -0
- package/src/utils/env.py +0 -134
- package/src/utils/puppeteer.js +0 -281
package/README.md
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Clone
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="./assets/images/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 AI-powered design 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
|
|
|
11
16
|
- **Multi-viewport screenshots**: Desktop (1920px), Tablet (768px), Mobile (375px)
|
|
12
17
|
- **HTML/CSS extraction**: Clean source files with unused CSS removal
|
|
13
18
|
- **Hover state capture**: Screenshots and CSS for interactive element states (phase 2)
|
|
14
|
-
- **AI structure analysis**:
|
|
19
|
+
- **AI structure analysis**: Built-in design analysis via Claude Code (no API key needed)
|
|
15
20
|
- **Asset extraction**: Downloads images, fonts, icons
|
|
16
21
|
- **Menu verification**: Tests responsive navigation functionality
|
|
17
22
|
|
|
@@ -31,7 +36,6 @@ git clone https://github.com/bienhoang/design-clone.git
|
|
|
31
36
|
cp -r design-clone ~/.claude/skills/design-clone
|
|
32
37
|
cd ~/.claude/skills/design-clone
|
|
33
38
|
npm install
|
|
34
|
-
pip install -r requirements.txt
|
|
35
39
|
```
|
|
36
40
|
|
|
37
41
|
### Verify Installation
|
|
@@ -68,7 +72,7 @@ Basic design capture:
|
|
|
68
72
|
Full pixel-perfect clone:
|
|
69
73
|
- All basic clone features
|
|
70
74
|
- Asset extraction (images, fonts, icons)
|
|
71
|
-
- AI structure analysis (
|
|
75
|
+
- AI structure analysis (built-in, no API key needed)
|
|
72
76
|
- Menu verification
|
|
73
77
|
- Design token extraction
|
|
74
78
|
|
|
@@ -85,7 +89,7 @@ cloned-design/
|
|
|
85
89
|
├── animations.css # Extracted @keyframes definitions
|
|
86
90
|
├── animation-tokens.json # Animation metadata (keyframes, transitions, timings)
|
|
87
91
|
├── hover.css # Generated :hover CSS rules (with --capture-hover)
|
|
88
|
-
├── structure.md # AI analysis (
|
|
92
|
+
├── structure.md # AI analysis (built-in)
|
|
89
93
|
├── tokens.json # Extracted design tokens
|
|
90
94
|
├── hover-states/ # Hover state captures (with --capture-hover)
|
|
91
95
|
│ ├── hover-N-normal.png # Element before hover
|
|
@@ -97,29 +101,20 @@ cloned-design/
|
|
|
97
101
|
└── icons/
|
|
98
102
|
```
|
|
99
103
|
|
|
100
|
-
## Environment Variables
|
|
101
|
-
|
|
102
|
-
```bash
|
|
103
|
-
# Optional: enables AI structure analysis
|
|
104
|
-
GEMINI_API_KEY=your-api-key
|
|
105
|
-
|
|
106
|
-
# Add to ~/.claude/.env for persistent config
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
Get your API key at: https://aistudio.google.com/apikey
|
|
110
|
-
|
|
111
104
|
## Requirements
|
|
112
105
|
|
|
113
106
|
- Node.js 18+
|
|
114
|
-
-
|
|
115
|
-
- Chrome or Chromium (auto-detected)
|
|
107
|
+
- Playwright + Chromium (auto-installed with `npm install`)
|
|
116
108
|
|
|
117
109
|
## CLI Commands
|
|
118
110
|
|
|
119
111
|
```bash
|
|
120
|
-
design-clone init [--force]
|
|
121
|
-
design-clone verify
|
|
122
|
-
design-clone
|
|
112
|
+
design-clone init [--force] # Install skill to ~/.claude/skills/
|
|
113
|
+
design-clone verify # Check installation status
|
|
114
|
+
design-clone update [--force] # Update to latest version
|
|
115
|
+
design-clone uninstall [--yes] # Remove skill installation
|
|
116
|
+
design-clone --version # Show version
|
|
117
|
+
design-clone help # Show usage help
|
|
123
118
|
```
|
|
124
119
|
|
|
125
120
|
## Troubleshooting
|
|
@@ -137,22 +132,14 @@ sudo apt install chromium-browser
|
|
|
137
132
|
export CHROME_PATH="/path/to/chrome"
|
|
138
133
|
```
|
|
139
134
|
|
|
140
|
-
###
|
|
135
|
+
### Playwright issues
|
|
141
136
|
|
|
142
137
|
```bash
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
pip3 install -r requirements.txt
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Puppeteer issues
|
|
149
|
-
|
|
150
|
-
```bash
|
|
151
|
-
# Install Puppeteer if not present
|
|
152
|
-
npm install puppeteer
|
|
138
|
+
# Install browsers (if not auto-installed)
|
|
139
|
+
npx playwright install chromium
|
|
153
140
|
|
|
154
141
|
# For Docker/CI environments
|
|
155
|
-
export
|
|
142
|
+
export PLAYWRIGHT_BROWSERS_PATH=/tmp/pw-browsers
|
|
156
143
|
```
|
|
157
144
|
|
|
158
145
|
See full troubleshooting guide: [docs/troubleshooting.md](docs/troubleshooting.md)
|
|
@@ -172,3 +159,9 @@ MIT - See [LICENSE](LICENSE)
|
|
|
172
159
|
## Credits
|
|
173
160
|
|
|
174
161
|
Built for use with [Claude Code](https://claude.ai/code) by Anthropic.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
<div align="center">
|
|
166
|
+
<sub>Made with ❤️ for the Claude Code community</sub>
|
|
167
|
+
</div>
|
package/SKILL.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: design-clone
|
|
3
|
-
description: Clone website designs via multi-viewport screenshots, HTML/CSS extraction, and
|
|
3
|
+
description: Clone website designs via multi-viewport screenshots, HTML/CSS extraction, and built-in AI analysis. Generates production HTML/CSS with Font Awesome icons, direct Unsplash images, and Japanese design principles. Commands - design:clone (basic), design:clone-px (pixel-perfect).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Design Clone Skill
|
|
7
7
|
|
|
8
|
-
Clone website designs with multi-viewport screenshots, HTML/CSS extraction, CSS filtering, and
|
|
8
|
+
Clone website designs with multi-viewport screenshots, HTML/CSS extraction, CSS filtering, and built-in AI structure analysis.
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
@@ -14,21 +14,18 @@ Clone website designs with multi-viewport screenshots, HTML/CSS extraction, CSS
|
|
|
14
14
|
- **Japanese Design Principles** - Ma, Kanso, Shibui, Seijaku for elegant designs
|
|
15
15
|
- **Multi-viewport Screenshots** - Desktop, tablet, mobile captures
|
|
16
16
|
- **Hover State Capture** - Interactive element screenshots and :hover CSS generation
|
|
17
|
-
- **
|
|
17
|
+
- **Built-in AI Analysis** - Design token extraction via Claude Code vision
|
|
18
18
|
- **ui-ux-pro-max Quality Check** - Accessibility, hover states, contrast validation
|
|
19
19
|
|
|
20
20
|
## Prerequisites
|
|
21
21
|
|
|
22
22
|
- Node.js 18+ with npm
|
|
23
|
-
- Python 3.9+ (for AI analysis)
|
|
24
23
|
- Chrome/Chromium browser
|
|
25
24
|
|
|
26
25
|
## Quick Setup
|
|
27
26
|
|
|
28
27
|
```bash
|
|
29
28
|
npm install
|
|
30
|
-
pip install -r requirements.txt
|
|
31
|
-
# Optional: Set GEMINI_API_KEY in .env for AI analysis
|
|
32
29
|
```
|
|
33
30
|
|
|
34
31
|
## Project Structure
|
|
@@ -44,17 +41,18 @@ design-clone/
|
|
|
44
41
|
│ │ ├── screenshot.js # Multi-viewport screenshots
|
|
45
42
|
│ │ ├── filter-css.js # CSS filtering
|
|
46
43
|
│ │ └── extract-assets.js
|
|
47
|
-
│ ├── ai/ # AI analysis
|
|
48
|
-
│ │
|
|
49
|
-
│ │
|
|
44
|
+
│ ├── ai/ # AI analysis prompt templates
|
|
45
|
+
│ │ └── prompts/ # Markdown prompts for Claude Code vision
|
|
46
|
+
│ │ ├── structure-analysis/
|
|
47
|
+
│ │ ├── design-tokens/
|
|
48
|
+
│ │ └── ux-audit/
|
|
50
49
|
│ ├── verification/ # Verification scripts
|
|
51
50
|
│ │ ├── verify-menu.js
|
|
52
51
|
│ │ └── verify-layout.js
|
|
53
52
|
│ ├── utils/ # Shared utilities
|
|
54
53
|
│ │ ├── browser.js
|
|
55
54
|
│ │ ├── puppeteer.js
|
|
56
|
-
│ │
|
|
57
|
-
│ │ └── env.py
|
|
55
|
+
│ │ └── env.js
|
|
58
56
|
│ └── post-process/ # Post-processing
|
|
59
57
|
│ ├── fetch-images.js
|
|
60
58
|
│ ├── inject-icons.js
|
|
@@ -78,14 +76,14 @@ Basic design capture with Font Awesome icons and Unsplash images.
|
|
|
78
76
|
**Workflow:**
|
|
79
77
|
```bash
|
|
80
78
|
# Step 1: Capture screenshots + HTML/CSS
|
|
81
|
-
node src/core/screenshot.js \
|
|
79
|
+
node src/core/capture/screenshot.js \
|
|
82
80
|
--url "URL" \
|
|
83
81
|
--output ./output \
|
|
84
82
|
--extract-html \
|
|
85
83
|
--extract-css
|
|
86
84
|
|
|
87
85
|
# Step 2: Filter unused CSS
|
|
88
|
-
node src/core/filter-css.js \
|
|
86
|
+
node src/core/css/filter-css.js \
|
|
89
87
|
--html ./output/source.html \
|
|
90
88
|
--css ./output/source-raw.css \
|
|
91
89
|
--output ./output/source.css
|
|
@@ -107,7 +105,7 @@ python3 $HOME/.claude/skills/ui-ux-pro-max/scripts/search.py "animation hover" -
|
|
|
107
105
|
|
|
108
106
|
### design:clone-site
|
|
109
107
|
|
|
110
|
-
Multi-page
|
|
108
|
+
Multi-page screenshot capture for Claude Code vision to generate new HTML/CSS.
|
|
111
109
|
|
|
112
110
|
```bash
|
|
113
111
|
/design:clone-site https://example.com
|
|
@@ -136,18 +134,13 @@ cloned-designs/{timestamp}-{domain}/
|
|
|
136
134
|
│ ├── desktop/*.png
|
|
137
135
|
│ ├── tablet/*.png
|
|
138
136
|
│ └── mobile/*.png
|
|
139
|
-
├──
|
|
140
|
-
|
|
141
|
-
│ ├── about.html
|
|
142
|
-
│ └── contact.html
|
|
143
|
-
├── styles.css # Merged + deduplicated CSS
|
|
144
|
-
└── manifest.json # Page metadata + mapping
|
|
137
|
+
├── manifest.json # Page metadata + screenshot paths
|
|
138
|
+
└── capture-results.json
|
|
145
139
|
```
|
|
146
140
|
|
|
147
141
|
**Features:**
|
|
148
142
|
- Auto-discovers pages from navigation (SPA-aware)
|
|
149
|
-
-
|
|
150
|
-
- Working internal links
|
|
143
|
+
- Multi-viewport screenshots (desktop, tablet, mobile)
|
|
151
144
|
- Progress reporting
|
|
152
145
|
- Graceful error handling (continues on page failures)
|
|
153
146
|
|
|
@@ -161,7 +154,7 @@ Pixel-perfect clone with full asset extraction and AI analysis.
|
|
|
161
154
|
|
|
162
155
|
```bash
|
|
163
156
|
# Step 1: Capture + Extract
|
|
164
|
-
node src/core/screenshot.js \
|
|
157
|
+
node src/core/capture/screenshot.js \
|
|
165
158
|
--url "URL" \
|
|
166
159
|
--output ./output \
|
|
167
160
|
--extract-html --extract-css \
|
|
@@ -169,27 +162,57 @@ node src/core/screenshot.js \
|
|
|
169
162
|
--full-page
|
|
170
163
|
|
|
171
164
|
# Step 2: Filter CSS
|
|
172
|
-
node src/core/filter-css.js \
|
|
165
|
+
node src/core/css/filter-css.js \
|
|
173
166
|
--html ./output/source.html \
|
|
174
167
|
--css ./output/source-raw.css \
|
|
175
168
|
--output ./output/source.css
|
|
176
169
|
|
|
177
170
|
# Step 3: Extract Assets (images, fonts, icons)
|
|
178
|
-
node src/core/extract-assets.js \
|
|
171
|
+
node src/core/media/extract-assets.js \
|
|
179
172
|
--url "URL" \
|
|
180
173
|
--output ./output
|
|
181
174
|
|
|
182
|
-
# Step 4: AI Structure Analysis (
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
#
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
175
|
+
# Step 4: AI Structure Analysis (built-in Claude Code vision)
|
|
176
|
+
# Select prompt based on available context (highest accuracy first):
|
|
177
|
+
# - If dom-hierarchy.json AND dimensions-summary.json exist:
|
|
178
|
+
# Read src/ai/prompts/structure-analysis/with-hierarchy.md
|
|
179
|
+
# Read output/dom-hierarchy.json
|
|
180
|
+
# Read output/dimensions-summary.json
|
|
181
|
+
# - Else if dimensions-summary.json exists:
|
|
182
|
+
# Read src/ai/prompts/structure-analysis/with-dimensions.md
|
|
183
|
+
# Read output/dimensions-summary.json
|
|
184
|
+
# - Else if source.html AND source.css exist:
|
|
185
|
+
# Read src/ai/prompts/structure-analysis/with-context.md
|
|
186
|
+
# Read output/source.html (first 100KB)
|
|
187
|
+
# Read output/source.css (first 100KB)
|
|
188
|
+
# - Else:
|
|
189
|
+
# Read src/ai/prompts/structure-analysis/basic.md
|
|
190
|
+
#
|
|
191
|
+
# Then: Read output/desktop.png (Claude vision analyzes the screenshot)
|
|
192
|
+
# If content-summary.md exists: Read output/content-summary.md
|
|
193
|
+
# Analyze following prompt instructions
|
|
194
|
+
# Write result to output/structure.md
|
|
195
|
+
|
|
196
|
+
# Step 5: Extract Design Tokens (built-in Claude Code vision)
|
|
197
|
+
# Select prompt:
|
|
198
|
+
# - If source.css exists:
|
|
199
|
+
# Read src/ai/prompts/design-tokens/with-css.md
|
|
200
|
+
# Read output/source.css (first 15KB)
|
|
201
|
+
# - Else:
|
|
202
|
+
# Read src/ai/prompts/design-tokens/basic.md
|
|
203
|
+
#
|
|
204
|
+
# Read output/desktop.png, output/tablet.png, output/mobile.png
|
|
205
|
+
# Analyze following prompt instructions
|
|
206
|
+
# Write JSON result to output/design-tokens.json
|
|
207
|
+
# Generate CSS custom properties and write to output/tokens.css
|
|
208
|
+
#
|
|
209
|
+
# Token CSS generation rules:
|
|
210
|
+
# - Map colors to --color-* variables
|
|
211
|
+
# - Map typography to --font-*, --font-size-*, --font-weight-*, --line-height-*
|
|
212
|
+
# - Map spacing to --space-* variables
|
|
213
|
+
# - Map border-radius to --radius-* variables
|
|
214
|
+
# - Map shadows to --shadow-* variables
|
|
215
|
+
# - Use :root {} selector
|
|
193
216
|
|
|
194
217
|
# Step 6: Verify Menu
|
|
195
218
|
node src/verification/verify-menu.js \
|
|
@@ -267,7 +290,7 @@ After generating HTML/CSS, verify these items using `ui-ux-pro-max` skill:
|
|
|
267
290
|
Automatically extracts @keyframes and transition properties when using `--extract-css`:
|
|
268
291
|
|
|
269
292
|
```bash
|
|
270
|
-
node src/core/screenshot.js --url https://example.com --output ./out --extract-css true
|
|
293
|
+
node src/core/capture/screenshot.js --url https://example.com --output ./out --extract-css true
|
|
271
294
|
```
|
|
272
295
|
|
|
273
296
|
**Output:**
|
|
@@ -279,7 +302,7 @@ node src/core/screenshot.js --url https://example.com --output ./out --extract-c
|
|
|
279
302
|
Capture interactive element hover states:
|
|
280
303
|
|
|
281
304
|
```bash
|
|
282
|
-
node src/core/screenshot.js --url https://example.com --output ./out --capture-hover
|
|
305
|
+
node src/core/capture/screenshot.js --url https://example.com --output ./out --capture-hover
|
|
283
306
|
```
|
|
284
307
|
|
|
285
308
|
**Output:**
|
|
@@ -297,16 +320,16 @@ Record scroll preview video (opt-in due to 3-5x capture time increase):
|
|
|
297
320
|
|
|
298
321
|
```bash
|
|
299
322
|
# WebM (native, no extra deps)
|
|
300
|
-
node src/core/screenshot.js --url https://example.com --output ./out --video
|
|
323
|
+
node src/core/capture/screenshot.js --url https://example.com --output ./out --video
|
|
301
324
|
|
|
302
325
|
# MP4 (requires ffmpeg)
|
|
303
|
-
node src/core/screenshot.js --url https://example.com --output ./out --video --video-format mp4
|
|
326
|
+
node src/core/capture/screenshot.js --url https://example.com --output ./out --video --video-format mp4
|
|
304
327
|
|
|
305
328
|
# GIF (requires ffmpeg)
|
|
306
|
-
node src/core/screenshot.js --url https://example.com --output ./out --video --video-format gif
|
|
329
|
+
node src/core/capture/screenshot.js --url https://example.com --output ./out --video --video-format gif
|
|
307
330
|
|
|
308
331
|
# Custom duration (default: 12000ms)
|
|
309
|
-
node src/core/screenshot.js --url https://example.com --output ./out --video --video-duration 8000
|
|
332
|
+
node src/core/capture/screenshot.js --url https://example.com --output ./out --video --video-duration 8000
|
|
310
333
|
```
|
|
311
334
|
|
|
312
335
|
**Output:**
|
|
@@ -332,7 +355,7 @@ npm install fluent-ffmpeg @ffmpeg-installer/ffmpeg
|
|
|
332
355
|
Create `.env` file (see `.env.example`):
|
|
333
356
|
|
|
334
357
|
```bash
|
|
335
|
-
|
|
358
|
+
# No API keys required for AI analysis (uses Claude Code built-in vision)
|
|
336
359
|
```
|
|
337
360
|
|
|
338
361
|
## Script Reference
|
|
@@ -350,8 +373,9 @@ GEMINI_API_KEY=your-key # Optional: enables AI structure analysis
|
|
|
350
373
|
| merge-css.js | src/core/ | Merge + deduplicate CSS |
|
|
351
374
|
| rewrite-links.js | src/core/ | Rewrite internal links |
|
|
352
375
|
| clone-site.js | bin/commands/ | Multi-page clone CLI |
|
|
353
|
-
|
|
|
354
|
-
|
|
|
376
|
+
| prompts/structure-analysis/*.md | src/ai/ | AI structure analysis prompts (Claude Code vision) |
|
|
377
|
+
| prompts/design-tokens/*.md | src/ai/ | Design token extraction prompts (Claude Code vision) |
|
|
378
|
+
| prompts/ux-audit/*.md | src/ai/ | UX audit prompts (Claude Code vision) |
|
|
355
379
|
| verify-menu.js | src/verification/ | Validate navigation structure |
|
|
356
380
|
| verify-layout.js | src/verification/ | Verify layout consistency |
|
|
357
381
|
| fetch-images.js | src/post-process/ | Fetch and optimize images |
|
package/bin/cli.js
CHANGED
|
@@ -3,15 +3,21 @@
|
|
|
3
3
|
* Design Clone Skill CLI
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
|
-
* design-clone init [--force]
|
|
7
|
-
* design-clone verify
|
|
8
|
-
* design-clone
|
|
9
|
-
* design-clone
|
|
6
|
+
* design-clone init [--force] Install skill to ~/.claude/skills/
|
|
7
|
+
* design-clone verify Check installation status
|
|
8
|
+
* design-clone update [--force] Update to latest version
|
|
9
|
+
* design-clone uninstall [--yes] Remove skill installation
|
|
10
|
+
* design-clone clone-site <url> Clone multiple pages
|
|
11
|
+
* design-clone help Show help
|
|
12
|
+
* design-clone --version Show version
|
|
10
13
|
*/
|
|
11
14
|
|
|
12
15
|
import { init } from './commands/init.js';
|
|
13
16
|
import { verify } from './commands/verify.js';
|
|
14
17
|
import { help } from './commands/help.js';
|
|
18
|
+
import { uninstall } from './commands/uninstall.js';
|
|
19
|
+
import { update } from './commands/update.js';
|
|
20
|
+
import { getVersion } from './utils/version.js';
|
|
15
21
|
import { cloneSite, parseArgs as parseCloneSiteArgs, showHelp as showCloneSiteHelp } from './commands/clone-site.js';
|
|
16
22
|
|
|
17
23
|
const [,, command, ...args] = process.argv;
|
|
@@ -41,6 +47,18 @@ async function main() {
|
|
|
41
47
|
console.log(JSON.stringify(result, null, 2));
|
|
42
48
|
}
|
|
43
49
|
break;
|
|
50
|
+
case 'uninstall':
|
|
51
|
+
case 'remove':
|
|
52
|
+
await uninstall(args);
|
|
53
|
+
break;
|
|
54
|
+
case 'update':
|
|
55
|
+
case 'upgrade':
|
|
56
|
+
await update(args);
|
|
57
|
+
break;
|
|
58
|
+
case '--version':
|
|
59
|
+
case '-v':
|
|
60
|
+
console.log(`design-clone v${getVersion()}`);
|
|
61
|
+
break;
|
|
44
62
|
case 'help':
|
|
45
63
|
case '--help':
|
|
46
64
|
case '-h':
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Clone Site Command
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Capture multi-viewport screenshots of multiple pages from a website.
|
|
5
|
+
* Screenshots are used by Claude Code vision to generate new HTML/CSS.
|
|
5
6
|
*
|
|
6
7
|
* Usage:
|
|
7
8
|
* design-clone clone-site <url> [options]
|
|
@@ -16,13 +17,9 @@
|
|
|
16
17
|
|
|
17
18
|
import fs from 'fs/promises';
|
|
18
19
|
import path from 'path';
|
|
19
|
-
import { fileURLToPath } from 'url';
|
|
20
20
|
|
|
21
|
-
import { discoverPages } from '../../src/core/discover-pages.js';
|
|
22
|
-
import { captureMultiplePages } from '../../src/core/multi-page-screenshot.js';
|
|
23
|
-
import { mergeCssFiles } from '../../src/core/merge-css.js';
|
|
24
|
-
import { rewriteLinks, createPageManifest, rewriteAllLinks } from '../../src/core/rewrite-links.js';
|
|
25
|
-
import { extractDesignTokens } from '../../src/core/design-tokens.js';
|
|
21
|
+
import { discoverPages } from '../../src/core/discovery/discover-pages.js';
|
|
22
|
+
import { captureMultiplePages } from '../../src/core/capture/multi-page-screenshot.js';
|
|
26
23
|
|
|
27
24
|
/**
|
|
28
25
|
* Generate output directory name
|
|
@@ -52,8 +49,7 @@ export function parseArgs(args) {
|
|
|
52
49
|
maxPages: 10,
|
|
53
50
|
viewports: ['desktop', 'tablet', 'mobile'],
|
|
54
51
|
skipConfirm: false,
|
|
55
|
-
output: null
|
|
56
|
-
ai: false
|
|
52
|
+
output: null
|
|
57
53
|
};
|
|
58
54
|
|
|
59
55
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -69,8 +65,6 @@ export function parseArgs(args) {
|
|
|
69
65
|
options.skipConfirm = true;
|
|
70
66
|
} else if (arg === '--output' && args[i + 1]) {
|
|
71
67
|
options.output = args[++i];
|
|
72
|
-
} else if (arg === '--ai') {
|
|
73
|
-
options.ai = true;
|
|
74
68
|
} else if (!arg.startsWith('--') && !options.url) {
|
|
75
69
|
options.url = arg;
|
|
76
70
|
}
|
|
@@ -80,7 +74,7 @@ export function parseArgs(args) {
|
|
|
80
74
|
}
|
|
81
75
|
|
|
82
76
|
/**
|
|
83
|
-
* Clone multiple pages from a website
|
|
77
|
+
* Clone multiple pages from a website (screenshot-only capture)
|
|
84
78
|
* @param {string} url - Target URL
|
|
85
79
|
* @param {Object} options - Clone options
|
|
86
80
|
* @returns {Promise<Object>} Clone result
|
|
@@ -91,9 +85,7 @@ export async function cloneSite(url, options = {}) {
|
|
|
91
85
|
pages: manualPages,
|
|
92
86
|
maxPages = 10,
|
|
93
87
|
viewports = ['desktop', 'tablet', 'mobile'],
|
|
94
|
-
|
|
95
|
-
output,
|
|
96
|
-
ai = false
|
|
88
|
+
output
|
|
97
89
|
} = options;
|
|
98
90
|
|
|
99
91
|
// Validate URL
|
|
@@ -111,11 +103,10 @@ export async function cloneSite(url, options = {}) {
|
|
|
111
103
|
console.error(`[clone-site] Output: ${outputDir}`);
|
|
112
104
|
|
|
113
105
|
// Step 1: Discover or use manual pages
|
|
114
|
-
console.error('\n[1/
|
|
106
|
+
console.error('\n[1/3] Discovering pages...');
|
|
115
107
|
|
|
116
108
|
let pageList;
|
|
117
109
|
if (manualPages && manualPages.length > 0) {
|
|
118
|
-
// Use manual page list
|
|
119
110
|
pageList = {
|
|
120
111
|
success: true,
|
|
121
112
|
pages: manualPages.map(p => ({
|
|
@@ -126,7 +117,6 @@ export async function cloneSite(url, options = {}) {
|
|
|
126
117
|
};
|
|
127
118
|
console.error(` Using ${pageList.pages.length} manual pages`);
|
|
128
119
|
} else {
|
|
129
|
-
// Auto-discover
|
|
130
120
|
pageList = await discoverPages(url, { maxPages });
|
|
131
121
|
if (!pageList.success) {
|
|
132
122
|
console.error(` Warning: Discovery failed - ${pageList.error}`);
|
|
@@ -135,13 +125,12 @@ export async function cloneSite(url, options = {}) {
|
|
|
135
125
|
console.error(` Found ${pageList.pages.length} pages`);
|
|
136
126
|
}
|
|
137
127
|
|
|
138
|
-
// Show discovered pages
|
|
139
128
|
for (const page of pageList.pages) {
|
|
140
129
|
console.error(` - ${page.path} (${page.name})`);
|
|
141
130
|
}
|
|
142
131
|
|
|
143
|
-
// Step 2: Capture all pages
|
|
144
|
-
console.error('\n[2/
|
|
132
|
+
// Step 2: Capture all pages (screenshots only)
|
|
133
|
+
console.error('\n[2/3] Capturing screenshots...');
|
|
145
134
|
|
|
146
135
|
const captureResult = await captureMultiplePages(pageList.pages, {
|
|
147
136
|
outputDir,
|
|
@@ -158,91 +147,30 @@ export async function cloneSite(url, options = {}) {
|
|
|
158
147
|
console.error(` Captured ${captureResult.stats.successfulPages}/${captureResult.stats.totalPages} pages`);
|
|
159
148
|
console.error(` Screenshots: ${captureResult.stats.totalScreenshots}`);
|
|
160
149
|
|
|
161
|
-
// Step 3:
|
|
162
|
-
console.error('\n[3/
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
} else {
|
|
180
|
-
console.error(` Warning: Merge failed - ${mergeResult.error}`);
|
|
181
|
-
}
|
|
182
|
-
} else {
|
|
183
|
-
console.error(' No CSS files to merge');
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Step 4: Extract design tokens (if --ai flag)
|
|
187
|
-
console.error('\n[4/6] Extracting design tokens...');
|
|
188
|
-
|
|
189
|
-
let hasTokens = false;
|
|
190
|
-
if (ai) {
|
|
191
|
-
if (process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY) {
|
|
192
|
-
const tokenResult = await extractDesignTokens(outputDir, mergedCssPath);
|
|
193
|
-
if (tokenResult.success) {
|
|
194
|
-
hasTokens = true;
|
|
195
|
-
console.error(` Created: tokens.css, design-tokens.json`);
|
|
196
|
-
} else {
|
|
197
|
-
console.error(` Warning: Token extraction failed - ${tokenResult.error}`);
|
|
198
|
-
if (tokenResult.hint) {
|
|
199
|
-
console.error(` Hint: ${tokenResult.hint}`);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
} else {
|
|
203
|
-
console.error(' Skipped: GEMINI_API_KEY not set');
|
|
204
|
-
console.error(' Hint: Set GEMINI_API_KEY in ~/.claude/.env for AI token extraction');
|
|
205
|
-
}
|
|
206
|
-
} else {
|
|
207
|
-
console.error(' Skipped (use --ai flag to enable)');
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Step 5: Rewrite links
|
|
211
|
-
console.error('\n[5/6] Rewriting links...');
|
|
212
|
-
|
|
213
|
-
const manifest = createPageManifest(pageList.pages, {
|
|
214
|
-
hasTokens,
|
|
150
|
+
// Step 3: Generate manifest
|
|
151
|
+
console.error('\n[3/3] Generating manifest...');
|
|
152
|
+
|
|
153
|
+
const manifest = {
|
|
154
|
+
baseUrl: url,
|
|
155
|
+
capturedAt: new Date().toISOString(),
|
|
156
|
+
pages: captureResult.pages
|
|
157
|
+
.filter(p => p.success)
|
|
158
|
+
.map(p => ({
|
|
159
|
+
path: p.path,
|
|
160
|
+
name: p.name,
|
|
161
|
+
originalUrl: p.url,
|
|
162
|
+
screenshots: Object.fromEntries(
|
|
163
|
+
Object.entries(p.screenshots)
|
|
164
|
+
.filter(([, v]) => !v.failed)
|
|
165
|
+
.map(([vp, v]) => [vp, path.relative(outputDir, v.path)])
|
|
166
|
+
)
|
|
167
|
+
})),
|
|
215
168
|
stats: {
|
|
216
|
-
totalPages:
|
|
169
|
+
totalPages: captureResult.stats.totalPages,
|
|
217
170
|
totalScreenshots: captureResult.stats.totalScreenshots,
|
|
218
|
-
cssReduction: mergeResult.stats?.reduction || '0%',
|
|
219
171
|
captureTimeMs: captureResult.stats.totalTimeMs
|
|
220
172
|
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Copy HTML files to pages/ directory and rewrite links
|
|
224
|
-
const pagesDir = path.join(outputDir, 'pages');
|
|
225
|
-
await fs.mkdir(pagesDir, { recursive: true });
|
|
226
|
-
|
|
227
|
-
for (const page of manifest.pages) {
|
|
228
|
-
const sourceHtml = path.join(outputDir, 'html', page.file);
|
|
229
|
-
const destHtml = path.join(pagesDir, page.file);
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
let html = await fs.readFile(sourceHtml, 'utf-8');
|
|
233
|
-
html = rewriteLinks(html, manifest, {
|
|
234
|
-
baseUrl: url,
|
|
235
|
-
injectTokensCss: hasTokens
|
|
236
|
-
});
|
|
237
|
-
await fs.writeFile(destHtml, html, 'utf-8');
|
|
238
|
-
console.error(` Rewritten: ${page.file}`);
|
|
239
|
-
} catch (err) {
|
|
240
|
-
console.error(` Warning: Failed to rewrite ${page.file}: ${err.message}`);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Step 6: Generate manifest
|
|
245
|
-
console.error('\n[6/6] Generating manifest...');
|
|
173
|
+
};
|
|
246
174
|
|
|
247
175
|
const manifestPath = path.join(outputDir, 'manifest.json');
|
|
248
176
|
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
@@ -260,7 +188,6 @@ export async function cloneSite(url, options = {}) {
|
|
|
260
188
|
outputDir: path.resolve(outputDir),
|
|
261
189
|
manifest,
|
|
262
190
|
captureResult,
|
|
263
|
-
mergeResult,
|
|
264
191
|
totalTimeMs: totalTime
|
|
265
192
|
};
|
|
266
193
|
}
|
|
@@ -272,7 +199,7 @@ export function showHelp() {
|
|
|
272
199
|
console.log(`
|
|
273
200
|
Usage: design-clone clone-site <url> [options]
|
|
274
201
|
|
|
275
|
-
|
|
202
|
+
Capture multi-viewport screenshots of multiple pages from a website.
|
|
276
203
|
|
|
277
204
|
Options:
|
|
278
205
|
--pages <paths> Comma-separated paths (e.g., /,/about,/contact)
|
|
@@ -280,13 +207,11 @@ Options:
|
|
|
280
207
|
--viewports <list> Viewport list (default: desktop,tablet,mobile)
|
|
281
208
|
--yes Skip confirmation prompt
|
|
282
209
|
--output <dir> Custom output directory
|
|
283
|
-
--ai Extract design tokens using Gemini AI (requires GEMINI_API_KEY)
|
|
284
210
|
|
|
285
211
|
Examples:
|
|
286
212
|
design-clone clone-site https://example.com
|
|
287
213
|
design-clone clone-site https://example.com --max-pages 5
|
|
288
214
|
design-clone clone-site https://example.com --pages /,/about,/contact
|
|
289
|
-
design-clone clone-site https://example.com --ai
|
|
290
215
|
`);
|
|
291
216
|
}
|
|
292
217
|
|