Upload app.py
Browse files
app.py
CHANGED
|
@@ -215,12 +215,14 @@ async def extract_tokens(pages_data, progress=gr.Progress()):
|
|
| 215 |
state.log("π₯οΈ DESKTOP EXTRACTION (1440px)")
|
| 216 |
state.log("=" * 60)
|
| 217 |
state.log("")
|
| 218 |
-
state.log("π‘ Enhanced extraction from
|
| 219 |
state.log(" 1. DOM computed styles (getComputedStyle)")
|
| 220 |
state.log(" 2. CSS variables (:root { --color: })")
|
| 221 |
state.log(" 3. SVG colors (fill, stroke)")
|
| 222 |
state.log(" 4. Inline styles (style='color:')")
|
| 223 |
state.log(" 5. Stylesheet rules (CSS files)")
|
|
|
|
|
|
|
| 224 |
state.log("")
|
| 225 |
|
| 226 |
progress(0.1, desc="π₯οΈ Extracting desktop tokens...")
|
|
@@ -292,6 +294,72 @@ async def extract_tokens(pages_data, progress=gr.Progress()):
|
|
| 292 |
state.mobile_normalized = normalizer_mod.normalize_tokens(state.mobile_raw)
|
| 293 |
state.log(f" β
Normalized: {len(state.mobile_normalized.colors)} colors, {len(state.mobile_normalized.typography)} typography, {len(state.mobile_normalized.spacing)} spacing")
|
| 294 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 295 |
progress(0.95, desc="π Preparing results...")
|
| 296 |
|
| 297 |
# Format results for Stage 1 UI
|
|
|
|
| 215 |
state.log("π₯οΈ DESKTOP EXTRACTION (1440px)")
|
| 216 |
state.log("=" * 60)
|
| 217 |
state.log("")
|
| 218 |
+
state.log("π‘ Enhanced extraction from 7 sources:")
|
| 219 |
state.log(" 1. DOM computed styles (getComputedStyle)")
|
| 220 |
state.log(" 2. CSS variables (:root { --color: })")
|
| 221 |
state.log(" 3. SVG colors (fill, stroke)")
|
| 222 |
state.log(" 4. Inline styles (style='color:')")
|
| 223 |
state.log(" 5. Stylesheet rules (CSS files)")
|
| 224 |
+
state.log(" 6. External CSS files (fetch & parse)")
|
| 225 |
+
state.log(" 7. Page content scan (brute-force)")
|
| 226 |
state.log("")
|
| 227 |
|
| 228 |
progress(0.1, desc="π₯οΈ Extracting desktop tokens...")
|
|
|
|
| 294 |
state.mobile_normalized = normalizer_mod.normalize_tokens(state.mobile_raw)
|
| 295 |
state.log(f" β
Normalized: {len(state.mobile_normalized.colors)} colors, {len(state.mobile_normalized.typography)} typography, {len(state.mobile_normalized.spacing)} spacing")
|
| 296 |
|
| 297 |
+
# === FIRECRAWL CSS EXTRACTION (Agent 1B) ===
|
| 298 |
+
progress(0.88, desc="π₯ Firecrawl CSS analysis...")
|
| 299 |
+
|
| 300 |
+
try:
|
| 301 |
+
from agents.firecrawl_extractor import extract_css_colors
|
| 302 |
+
|
| 303 |
+
# Get base URL for Firecrawl
|
| 304 |
+
base_url = selected_urls[0] if selected_urls else state.base_url
|
| 305 |
+
|
| 306 |
+
# Extract CSS colors using Firecrawl
|
| 307 |
+
firecrawl_result = await extract_css_colors(
|
| 308 |
+
url=base_url,
|
| 309 |
+
api_key=None, # Will use fallback method
|
| 310 |
+
log_callback=state.log
|
| 311 |
+
)
|
| 312 |
+
|
| 313 |
+
# Merge Firecrawl colors into desktop normalized
|
| 314 |
+
firecrawl_colors = firecrawl_result.get("colors", {})
|
| 315 |
+
|
| 316 |
+
if firecrawl_colors:
|
| 317 |
+
state.log("")
|
| 318 |
+
state.log("π Merging Firecrawl colors with Playwright extraction...")
|
| 319 |
+
|
| 320 |
+
# Count new colors
|
| 321 |
+
new_colors_count = 0
|
| 322 |
+
|
| 323 |
+
for hex_val, color_data in firecrawl_colors.items():
|
| 324 |
+
# Check if this color already exists
|
| 325 |
+
existing = False
|
| 326 |
+
for name, existing_color in state.desktop_normalized.colors.items():
|
| 327 |
+
if existing_color.value.lower() == hex_val.lower():
|
| 328 |
+
existing = True
|
| 329 |
+
# Update frequency
|
| 330 |
+
existing_color.frequency += color_data.get("frequency", 1)
|
| 331 |
+
if "firecrawl" not in existing_color.contexts:
|
| 332 |
+
existing_color.contexts.append("firecrawl")
|
| 333 |
+
break
|
| 334 |
+
|
| 335 |
+
if not existing:
|
| 336 |
+
# Add new color from Firecrawl
|
| 337 |
+
from core.token_schema import ColorToken, TokenSource, Confidence
|
| 338 |
+
|
| 339 |
+
new_token = ColorToken(
|
| 340 |
+
value=hex_val,
|
| 341 |
+
frequency=color_data.get("frequency", 1),
|
| 342 |
+
contexts=["firecrawl"] + color_data.get("contexts", []),
|
| 343 |
+
elements=["css-file"],
|
| 344 |
+
css_properties=color_data.get("sources", []),
|
| 345 |
+
contrast_white=color_data.get("contrast_white", 0),
|
| 346 |
+
contrast_black=color_data.get("contrast_black", 0),
|
| 347 |
+
source=TokenSource.DETECTED,
|
| 348 |
+
confidence=Confidence.MEDIUM,
|
| 349 |
+
)
|
| 350 |
+
|
| 351 |
+
# Generate name
|
| 352 |
+
new_token.suggested_name = f"color.firecrawl.{len(state.desktop_normalized.colors)}"
|
| 353 |
+
|
| 354 |
+
state.desktop_normalized.colors[hex_val] = new_token
|
| 355 |
+
new_colors_count += 1
|
| 356 |
+
|
| 357 |
+
state.log(f" β
Added {new_colors_count} new colors from Firecrawl")
|
| 358 |
+
state.log(f" π Total colors now: {len(state.desktop_normalized.colors)}")
|
| 359 |
+
|
| 360 |
+
except Exception as e:
|
| 361 |
+
state.log(f" β οΈ Firecrawl extraction skipped: {str(e)}")
|
| 362 |
+
|
| 363 |
progress(0.95, desc="π Preparing results...")
|
| 364 |
|
| 365 |
# Format results for Stage 1 UI
|