mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-13 02:41:50 +08:00
- Implemented main render function for the issue discovery view. - Added data loading functions to fetch discoveries, details, findings, and progress. - Created rendering functions for discovery list and detail sections. - Introduced filtering and searching capabilities for findings. - Implemented actions for exporting and dismissing findings. - Added polling mechanism to track discovery progress. - Included utility functions for HTML escaping and cleanup.
448 lines
10 KiB
Markdown
448 lines
10 KiB
Markdown
# Screenshot Helper
|
|
|
|
Guide for capturing screenshots using Chrome MCP.
|
|
|
|
## Overview
|
|
|
|
This script helps capture screenshots of web interfaces for the software manual using Chrome MCP or fallback methods.
|
|
|
|
## Chrome MCP Prerequisites
|
|
|
|
### Check MCP Availability
|
|
|
|
```javascript
|
|
async function checkChromeMCPAvailability() {
|
|
try {
|
|
// Attempt to get Chrome version via MCP
|
|
const version = await mcp__chrome__getVersion();
|
|
return {
|
|
available: true,
|
|
browser: version.browser,
|
|
version: version.version
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
available: false,
|
|
error: error.message
|
|
};
|
|
}
|
|
}
|
|
```
|
|
|
|
### MCP Configuration
|
|
|
|
Expected Claude configuration for Chrome MCP:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"chrome": {
|
|
"command": "npx",
|
|
"args": ["@anthropic-ai/mcp-chrome"],
|
|
"env": {
|
|
"CHROME_PATH": "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Screenshot Workflow
|
|
|
|
### Step 1: Prepare Environment
|
|
|
|
```javascript
|
|
async function prepareScreenshotEnvironment(workDir, config) {
|
|
const screenshotDir = `${workDir}/screenshots`;
|
|
|
|
// Create directory
|
|
Bash({ command: `mkdir -p "${screenshotDir}"` });
|
|
|
|
// Check Chrome MCP
|
|
const chromeMCP = await checkChromeMCPAvailability();
|
|
|
|
if (!chromeMCP.available) {
|
|
console.log('Chrome MCP not available. Will generate manual guide.');
|
|
return { mode: 'manual' };
|
|
}
|
|
|
|
// Start development server if needed
|
|
if (config.screenshot_config?.dev_command) {
|
|
const server = await startDevServer(config);
|
|
return { mode: 'auto', server, screenshotDir };
|
|
}
|
|
|
|
return { mode: 'auto', screenshotDir };
|
|
}
|
|
```
|
|
|
|
### Step 2: Start Development Server
|
|
|
|
```javascript
|
|
async function startDevServer(config) {
|
|
const devCommand = config.screenshot_config.dev_command;
|
|
const devUrl = config.screenshot_config.dev_url;
|
|
|
|
// Start server in background
|
|
const server = Bash({
|
|
command: devCommand,
|
|
run_in_background: true
|
|
});
|
|
|
|
console.log(`Starting dev server: ${devCommand}`);
|
|
|
|
// Wait for server to be ready
|
|
const ready = await waitForServer(devUrl, 30000);
|
|
|
|
if (!ready) {
|
|
throw new Error(`Server at ${devUrl} did not start in time`);
|
|
}
|
|
|
|
console.log(`Dev server ready at ${devUrl}`);
|
|
|
|
return server;
|
|
}
|
|
|
|
async function waitForServer(url, timeout = 30000) {
|
|
const start = Date.now();
|
|
|
|
while (Date.now() - start < timeout) {
|
|
try {
|
|
const response = await fetch(url, { method: 'HEAD' });
|
|
if (response.ok) return true;
|
|
} catch (e) {
|
|
// Server not ready
|
|
}
|
|
await sleep(1000);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
```
|
|
|
|
### Step 3: Capture Screenshots
|
|
|
|
```javascript
|
|
async function captureScreenshots(screenshots, config, workDir) {
|
|
const results = {
|
|
captured: [],
|
|
failed: []
|
|
};
|
|
|
|
const devUrl = config.screenshot_config.dev_url;
|
|
const screenshotDir = `${workDir}/screenshots`;
|
|
|
|
for (const ss of screenshots) {
|
|
try {
|
|
// Build full URL
|
|
const fullUrl = new URL(ss.url, devUrl).href;
|
|
|
|
console.log(`Capturing: ${ss.id} (${fullUrl})`);
|
|
|
|
// Configure capture options
|
|
const options = {
|
|
url: fullUrl,
|
|
viewport: { width: 1280, height: 800 },
|
|
fullPage: ss.fullPage || false
|
|
};
|
|
|
|
// Wait for specific element if specified
|
|
if (ss.wait_for) {
|
|
options.waitFor = ss.wait_for;
|
|
}
|
|
|
|
// Capture specific element if selector provided
|
|
if (ss.selector) {
|
|
options.selector = ss.selector;
|
|
}
|
|
|
|
// Add delay for animations
|
|
await sleep(500);
|
|
|
|
// Capture via Chrome MCP
|
|
const result = await mcp__chrome__screenshot(options);
|
|
|
|
// Save as PNG
|
|
const filename = `${ss.id}.png`;
|
|
Write(`${screenshotDir}/${filename}`, result.data, { encoding: 'base64' });
|
|
|
|
results.captured.push({
|
|
id: ss.id,
|
|
file: filename,
|
|
url: ss.url,
|
|
description: ss.description,
|
|
size: result.data.length
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error(`Failed to capture ${ss.id}:`, error.message);
|
|
results.failed.push({
|
|
id: ss.id,
|
|
url: ss.url,
|
|
error: error.message
|
|
});
|
|
}
|
|
}
|
|
|
|
return results;
|
|
}
|
|
```
|
|
|
|
### Step 4: Generate Manifest
|
|
|
|
```javascript
|
|
function generateScreenshotManifest(results, workDir) {
|
|
const manifest = {
|
|
generated: new Date().toISOString(),
|
|
total: results.captured.length + results.failed.length,
|
|
captured: results.captured.length,
|
|
failed: results.failed.length,
|
|
screenshots: results.captured,
|
|
failures: results.failed
|
|
};
|
|
|
|
Write(`${workDir}/screenshots/screenshots-manifest.json`,
|
|
JSON.stringify(manifest, null, 2));
|
|
|
|
return manifest;
|
|
}
|
|
```
|
|
|
|
### Step 5: Cleanup
|
|
|
|
```javascript
|
|
async function cleanupScreenshotEnvironment(env) {
|
|
if (env.server) {
|
|
console.log('Stopping dev server...');
|
|
KillShell({ shell_id: env.server.task_id });
|
|
}
|
|
}
|
|
```
|
|
|
|
## Main Runner
|
|
|
|
```javascript
|
|
async function runScreenshotCapture(workDir, screenshots) {
|
|
const config = JSON.parse(Read(`${workDir}/manual-config.json`));
|
|
|
|
// Prepare environment
|
|
const env = await prepareScreenshotEnvironment(workDir, config);
|
|
|
|
if (env.mode === 'manual') {
|
|
// Generate manual capture guide
|
|
generateManualCaptureGuide(screenshots, workDir);
|
|
return { success: false, mode: 'manual' };
|
|
}
|
|
|
|
try {
|
|
// Capture screenshots
|
|
const results = await captureScreenshots(screenshots, config, workDir);
|
|
|
|
// Generate manifest
|
|
const manifest = generateScreenshotManifest(results, workDir);
|
|
|
|
// Generate manual guide for failed captures
|
|
if (results.failed.length > 0) {
|
|
generateManualCaptureGuide(results.failed, workDir);
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
captured: results.captured.length,
|
|
failed: results.failed.length,
|
|
manifest
|
|
};
|
|
|
|
} finally {
|
|
// Cleanup
|
|
await cleanupScreenshotEnvironment(env);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Manual Capture Fallback
|
|
|
|
When Chrome MCP is unavailable:
|
|
|
|
```javascript
|
|
function generateManualCaptureGuide(screenshots, workDir) {
|
|
const guide = `
|
|
# Manual Screenshot Capture Guide
|
|
|
|
Chrome MCP is not available. Please capture screenshots manually.
|
|
|
|
## Prerequisites
|
|
|
|
1. Start your development server
|
|
2. Open a browser
|
|
3. Use a screenshot tool (Snipping Tool, Screenshot, etc.)
|
|
|
|
## Screenshots Required
|
|
|
|
${screenshots.map((ss, i) => `
|
|
### ${i + 1}. ${ss.id}
|
|
|
|
- **URL**: ${ss.url}
|
|
- **Description**: ${ss.description}
|
|
- **Save as**: \`screenshots/${ss.id}.png\`
|
|
${ss.selector ? `- **Capture area**: \`${ss.selector}\` element only` : '- **Type**: Full page or viewport'}
|
|
${ss.wait_for ? `- **Wait for**: \`${ss.wait_for}\` to be visible` : ''}
|
|
|
|
**Steps:**
|
|
1. Navigate to ${ss.url}
|
|
${ss.wait_for ? `2. Wait for ${ss.wait_for} to appear` : ''}
|
|
${ss.selector ? `2. Capture only the ${ss.selector} area` : '2. Capture the full viewport'}
|
|
3. Save as \`${ss.id}.png\`
|
|
`).join('\n')}
|
|
|
|
## After Capturing
|
|
|
|
1. Place all PNG files in the \`screenshots/\` directory
|
|
2. Ensure filenames match exactly (case-sensitive)
|
|
3. Run Phase 5 (HTML Assembly) to continue
|
|
|
|
## Screenshot Specifications
|
|
|
|
- **Format**: PNG
|
|
- **Width**: 1280px recommended
|
|
- **Quality**: High
|
|
- **Annotations**: None (add in post-processing if needed)
|
|
`;
|
|
|
|
Write(`${workDir}/screenshots/MANUAL_CAPTURE.md`, guide);
|
|
}
|
|
```
|
|
|
|
## Advanced Options
|
|
|
|
### Viewport Sizes
|
|
|
|
```javascript
|
|
const viewportPresets = {
|
|
desktop: { width: 1280, height: 800 },
|
|
tablet: { width: 768, height: 1024 },
|
|
mobile: { width: 375, height: 667 },
|
|
wide: { width: 1920, height: 1080 }
|
|
};
|
|
|
|
async function captureResponsive(ss, config, workDir) {
|
|
const results = [];
|
|
|
|
for (const [name, viewport] of Object.entries(viewportPresets)) {
|
|
const result = await mcp__chrome__screenshot({
|
|
url: ss.url,
|
|
viewport
|
|
});
|
|
|
|
const filename = `${ss.id}-${name}.png`;
|
|
Write(`${workDir}/screenshots/${filename}`, result.data, { encoding: 'base64' });
|
|
|
|
results.push({ viewport: name, file: filename });
|
|
}
|
|
|
|
return results;
|
|
}
|
|
```
|
|
|
|
### Before/After Comparisons
|
|
|
|
```javascript
|
|
async function captureInteraction(ss, config, workDir) {
|
|
const baseUrl = config.screenshot_config.dev_url;
|
|
const fullUrl = new URL(ss.url, baseUrl).href;
|
|
|
|
// Capture before state
|
|
const before = await mcp__chrome__screenshot({
|
|
url: fullUrl,
|
|
viewport: { width: 1280, height: 800 }
|
|
});
|
|
Write(`${workDir}/screenshots/${ss.id}-before.png`, before.data, { encoding: 'base64' });
|
|
|
|
// Perform interaction (click, type, etc.)
|
|
if (ss.interaction) {
|
|
await mcp__chrome__click({ selector: ss.interaction.click });
|
|
await sleep(500);
|
|
}
|
|
|
|
// Capture after state
|
|
const after = await mcp__chrome__screenshot({
|
|
url: fullUrl,
|
|
viewport: { width: 1280, height: 800 }
|
|
});
|
|
Write(`${workDir}/screenshots/${ss.id}-after.png`, after.data, { encoding: 'base64' });
|
|
|
|
return {
|
|
before: `${ss.id}-before.png`,
|
|
after: `${ss.id}-after.png`
|
|
};
|
|
}
|
|
```
|
|
|
|
### Screenshot Annotation
|
|
|
|
```javascript
|
|
function generateAnnotationGuide(screenshots, workDir) {
|
|
const guide = `
|
|
# Screenshot Annotation Guide
|
|
|
|
For screenshots requiring callouts or highlights:
|
|
|
|
## Tools
|
|
- macOS: Preview, Skitch
|
|
- Windows: Snipping Tool, ShareX
|
|
- Cross-platform: Greenshot, Lightshot
|
|
|
|
## Annotation Guidelines
|
|
|
|
1. **Callouts**: Use numbered circles (1, 2, 3)
|
|
2. **Highlights**: Use semi-transparent rectangles
|
|
3. **Arrows**: Point from text to element
|
|
4. **Text**: Use sans-serif font, 12-14pt
|
|
|
|
## Color Scheme
|
|
|
|
- Primary: #0d6efd (blue)
|
|
- Secondary: #6c757d (gray)
|
|
- Success: #198754 (green)
|
|
- Warning: #ffc107 (yellow)
|
|
- Danger: #dc3545 (red)
|
|
|
|
## Screenshots Needing Annotation
|
|
|
|
${screenshots.filter(s => s.annotate).map(ss => `
|
|
- **${ss.id}**: ${ss.description}
|
|
- Highlight: ${ss.annotate.highlight || 'N/A'}
|
|
- Callouts: ${ss.annotate.callouts?.join(', ') || 'N/A'}
|
|
`).join('\n')}
|
|
`;
|
|
|
|
Write(`${workDir}/screenshots/ANNOTATION_GUIDE.md`, guide);
|
|
}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Chrome MCP Not Found
|
|
|
|
1. Check Claude MCP configuration
|
|
2. Verify Chrome is installed
|
|
3. Check CHROME_PATH environment variable
|
|
|
|
### Screenshots Are Blank
|
|
|
|
1. Increase wait time before capture
|
|
2. Check if page requires authentication
|
|
3. Verify URL is correct
|
|
|
|
### Elements Not Visible
|
|
|
|
1. Scroll element into view
|
|
2. Expand collapsed sections
|
|
3. Wait for animations to complete
|
|
|
|
### Server Not Starting
|
|
|
|
1. Check if port is already in use
|
|
2. Verify dev command is correct
|
|
3. Check for startup errors in logs
|