chatui-helper / capture_docs_screenshots.py
milwright
add hf_token authentication for configuration tab
00daf25
raw
history blame
11.7 kB
"""
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())