Spaces:
Running
Running
| """ | |
| Specialized screenshot capture for documentation steps in support_docs.py | |
| Captures specific HuggingFace Spaces deployment screenshots | |
| """ | |
| import asyncio | |
| import os | |
| from pathlib import Path | |
| from playwright.async_api import async_playwright | |
| import logging | |
| import json | |
| from datetime import datetime | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s') | |
| logger = logging.getLogger(__name__) | |
| # Documentation-specific screenshot configurations | |
| DOCS_SCREENSHOTS = { | |
| # Step 1: Generate & Create Space | |
| "huggingface_spaces_page": { | |
| "url": "https://huggingface.co/spaces", | |
| "description": "HuggingFace Spaces main page", | |
| "output": "img/hf_spaces_main.png", | |
| "actions": [], | |
| "wait_time": 3000 | |
| }, | |
| "new_space_button": { | |
| "url": "https://huggingface.co/spaces", | |
| "description": "New Space button", | |
| "output": "img/hf_new_space_button.png", | |
| "actions": [], | |
| "selector": "button:has-text('New Space')", | |
| "wait_time": 2000 | |
| }, | |
| "space_creation_form": { | |
| "url": "https://huggingface.co/new-space", | |
| "description": "Space creation form (img17.png replacement)", | |
| "output": "img/img17.png", | |
| "actions": [], | |
| "wait_time": 3000 | |
| }, | |
| "hardware_selection": { | |
| "url": "https://huggingface.co/new-space", | |
| "description": "Hardware selection options (img16.png replacement)", | |
| "output": "img/img16.png", | |
| "actions": [ | |
| {"type": "scroll", "y": 400} | |
| ], | |
| "wait_time": 2000 | |
| }, | |
| # Step 2: Upload Files | |
| "files_tab": { | |
| "url": "https://huggingface.co/spaces/{username}/{space_name}/tree/main", | |
| "description": "Files tab in Space", | |
| "output": "img/hf_files_tab.png", | |
| "actions": [], | |
| "wait_time": 2000 | |
| }, | |
| "upload_files_button": { | |
| "url": "https://huggingface.co/spaces/{username}/{space_name}/tree/main", | |
| "description": "Upload files interface (img12.png replacement)", | |
| "output": "img/img12.png", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Upload files')"} | |
| ], | |
| "wait_time": 2000 | |
| }, | |
| "files_after_upload": { | |
| "url": "https://huggingface.co/spaces/{username}/{space_name}/tree/main", | |
| "description": "Files view after upload (img8.png replacement)", | |
| "output": "img/img8.png", | |
| "actions": [], | |
| "wait_time": 2000 | |
| }, | |
| # Step 3: Configure API Secrets | |
| "settings_tab": { | |
| "url": "https://huggingface.co/spaces/{username}/{space_name}/settings", | |
| "description": "Settings tab navigation (img4.png replacement)", | |
| "output": "img/img4.png", | |
| "actions": [], | |
| "wait_time": 2000 | |
| }, | |
| "variables_secrets_section": { | |
| "url": "https://huggingface.co/spaces/{username}/{space_name}/settings", | |
| "description": "Variables and secrets section", | |
| "output": "img/hf_variables_secrets.png", | |
| "actions": [ | |
| {"type": "scroll", "y": 300} | |
| ], | |
| "wait_time": 2000 | |
| }, | |
| "new_secret_form": { | |
| "url": "https://huggingface.co/spaces/{username}/{space_name}/settings", | |
| "description": "New secret configuration form (img3.png replacement)", | |
| "output": "img/img3.png", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('New secret')"} | |
| ], | |
| "wait_time": 2000 | |
| }, | |
| # Step 4: Monitor Build | |
| "build_logs": { | |
| "url": "https://huggingface.co/spaces/{username}/{space_name}", | |
| "description": "Build process logs (img7.png replacement)", | |
| "output": "img/img7.png", | |
| "actions": [], | |
| "wait_time": 3000 | |
| }, | |
| "successful_deployment": { | |
| "url": "https://huggingface.co/spaces/{username}/{space_name}", | |
| "description": "Successfully deployed Space (img1.png replacement)", | |
| "output": "img/img1.png", | |
| "actions": [], | |
| "wait_time": 5000 | |
| } | |
| } | |
| # Local app screenshots for main documentation | |
| LOCAL_APP_SCREENSHOTS = { | |
| "config_tab_full": { | |
| "url": "http://localhost:7860", | |
| "description": "Full configuration tab", | |
| "output": "img/config_tab_full.png", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Configure Space')"} | |
| ], | |
| "wait_time": 2000, | |
| "full_page": True | |
| }, | |
| "template_selection": { | |
| "url": "http://localhost:7860", | |
| "description": "Template selection with dropdown open", | |
| "output": "img/template_selection.png", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Configure Space')"}, | |
| {"type": "wait", "time": 1000}, | |
| {"type": "click", "selector": "div.gr-dropdown"} | |
| ], | |
| "wait_time": 1500 | |
| }, | |
| "space_identity_section": { | |
| "url": "http://localhost:7860", | |
| "description": "Space identity configuration", | |
| "output": "img/space_identity_config.png", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Configure Space')"}, | |
| {"type": "scroll", "y": 200} | |
| ], | |
| "wait_time": 1000 | |
| }, | |
| "system_config_section": { | |
| "url": "http://localhost:7860", | |
| "description": "System configuration section", | |
| "output": "img/system_config_section.png", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Configure Space')"}, | |
| {"type": "scroll", "y": 600} | |
| ], | |
| "wait_time": 1000 | |
| }, | |
| "api_config_section": { | |
| "url": "http://localhost:7860", | |
| "description": "API configuration section", | |
| "output": "img/api_config_section.png", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Configure Space')"}, | |
| {"type": "scroll", "y": 1200} | |
| ], | |
| "wait_time": 1000 | |
| }, | |
| "preview_tab_active": { | |
| "url": "http://localhost:7860", | |
| "description": "Preview tab with active chat", | |
| "output": "img/preview_tab_active.png", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Preview')"}, | |
| {"type": "wait", "time": 2000}, | |
| {"type": "type", "selector": "textarea", "text": "Tell me about quantum mechanics"}, | |
| {"type": "click", "selector": "button:has-text('Send')"}, | |
| {"type": "wait", "time": 4000} | |
| ], | |
| "wait_time": 1000 | |
| }, | |
| "docs_tab_overview": { | |
| "url": "http://localhost:7860", | |
| "description": "Documentation tab overview", | |
| "output": "img/docs_tab_overview.png", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Docs')"} | |
| ], | |
| "wait_time": 2000 | |
| }, | |
| "docs_deployment_steps": { | |
| "url": "http://localhost:7860", | |
| "description": "Deployment steps accordion expanded", | |
| "output": "img/docs_deployment_steps.png", | |
| "actions": [ | |
| {"type": "click", "selector": "button:has-text('Docs')"}, | |
| {"type": "wait", "time": 1000}, | |
| {"type": "click", "selector": "button:has-text('🗳️ Step 3: Generate & Deploy')"} | |
| ], | |
| "wait_time": 2000 | |
| } | |
| } | |
| async def capture_screenshot(page, config, replace_values=None): | |
| """Capture a single screenshot based on configuration""" | |
| url = config['url'] | |
| if replace_values: | |
| for key, value in replace_values.items(): | |
| url = url.replace(f"{{{key}}}", value) | |
| logger.info(f"Capturing: {config['description']} -> {config['output']}") | |
| try: | |
| # Navigate to URL | |
| await page.goto(url, wait_until='networkidle') | |
| # Execute actions | |
| for action in config.get('actions', []): | |
| if action['type'] == 'click': | |
| await page.click(action['selector']) | |
| await page.wait_for_timeout(500) | |
| elif action['type'] == 'type': | |
| await page.fill(action['selector'], action['text']) | |
| elif action['type'] == 'wait': | |
| await page.wait_for_timeout(action['time']) | |
| elif action['type'] == 'scroll': | |
| await page.evaluate(f"window.scrollBy(0, {action['y']})") | |
| await page.wait_for_timeout(500) | |
| # Wait for any animations | |
| await page.wait_for_timeout(config.get('wait_time', 1000)) | |
| # Take screenshot | |
| output_path = Path(config['output']) | |
| output_path.parent.mkdir(parents=True, exist_ok=True) | |
| screenshot_options = { | |
| "path": str(output_path), | |
| "full_page": config.get('full_page', False) | |
| } | |
| if config.get('selector'): | |
| element = page.locator(config['selector']) | |
| await element.screenshot(path=str(output_path)) | |
| else: | |
| await page.screenshot(**screenshot_options) | |
| logger.info(f"✅ Saved: {output_path}") | |
| return True | |
| except Exception as e: | |
| logger.error(f"❌ Failed: {config['description']} - {str(e)}") | |
| return False | |
| async def capture_huggingface_screenshots(username=None, space_name=None): | |
| """Capture HuggingFace-specific screenshots""" | |
| logger.info("Capturing HuggingFace screenshots...") | |
| if not username or not space_name: | |
| logger.warning("No username/space_name provided. Using placeholders.") | |
| username = "your-username" | |
| space_name = "your-space-name" | |
| replace_values = { | |
| "username": username, | |
| "space_name": space_name | |
| } | |
| async with async_playwright() as p: | |
| browser = await p.chromium.launch(headless=False) | |
| context = await browser.new_context( | |
| viewport={'width': 1280, 'height': 800}, | |
| device_scale_factor=2 | |
| ) | |
| page = await context.new_page() | |
| for name, config in DOCS_SCREENSHOTS.items(): | |
| await capture_screenshot(page, config, replace_values) | |
| await page.wait_for_timeout(1000) | |
| await browser.close() | |
| async def capture_local_app_screenshots(): | |
| """Capture local app screenshots""" | |
| logger.info("Capturing local app screenshots...") | |
| logger.info("Make sure the app is running on http://localhost:7860") | |
| async with async_playwright() as p: | |
| browser = await p.chromium.launch(headless=False) | |
| context = await browser.new_context( | |
| viewport={'width': 1280, 'height': 800}, | |
| device_scale_factor=2 | |
| ) | |
| page = await context.new_page() | |
| for name, config in LOCAL_APP_SCREENSHOTS.items(): | |
| await capture_screenshot(page, config) | |
| await page.wait_for_timeout(1000) | |
| await browser.close() | |
| async def main(): | |
| """Main entry point""" | |
| import sys | |
| if len(sys.argv) > 1: | |
| if sys.argv[1] == "local": | |
| await capture_local_app_screenshots() | |
| elif sys.argv[1] == "huggingface": | |
| username = sys.argv[2] if len(sys.argv) > 2 else None | |
| space_name = sys.argv[3] if len(sys.argv) > 3 else None | |
| await capture_huggingface_screenshots(username, space_name) | |
| else: | |
| logger.error("Usage: python capture_docs_screenshots.py [local|huggingface] [username] [space_name]") | |
| else: | |
| # Capture both sets | |
| await capture_local_app_screenshots() | |
| logger.info("\nNow capturing HuggingFace screenshots...") | |
| await capture_huggingface_screenshots() | |
| if __name__ == "__main__": | |
| asyncio.run(main()) |