Files
Claude-Code-Workflow/.claude/skills/software-manual/scripts/screenshot-helper.md
catlog22 7aa1cda367 feat: add issue discovery view for managing discovery sessions and findings
- 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.
2025-12-28 17:21:07 +08:00

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