Skip to content

Commit d47c34e

Browse files
committed
Refactor CSS: Extract homepage-specific styles into separate file
Step 1 of incremental CSS refactoring to manage growing styles.css file. Changes: - Created extract_homepage_css.py script to identify and extract homepage-only CSS - Generated homepage.css (278 lines) with 39 homepage-specific rules: * Hero section (.hero, .hero-content, .hero-title, .hero-subtitle, .hero-tabs) * Catalog controls (.catalog-controls-wrapper, .catalog-results-header, .catalog-grid) * Sort modal (.sort-btn, .sort-modal, .sort-modal-*) * Search UI (.search-icon-catalog, .results-count) - Added extra_styles block to base.html for page-specific CSS includes - Updated homepage.html to include homepage.css - Restored .stats-grid, .stat-item CSS (was incorrectly removed, still used in detail pages) Architecture: - styles.css remains the foundation (loaded on all pages, 7,534 lines) - homepage.css contains homepage-only styles (loaded only on index.html, 278 lines) - Future: Extract detail-page.css and skill-page.css following same pattern
1 parent b155295 commit d47c34e

5 files changed

Lines changed: 441 additions & 1 deletion

File tree

scripts/extract_homepage_css.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Extract homepage-specific CSS from styles.css.
4+
This script identifies CSS rules that are only used in the homepage (index.html)
5+
and not in other pages (detail pages, skill pages).
6+
"""
7+
8+
import re
9+
from pathlib import Path
10+
11+
# Define paths
12+
PORTAL_DIR = Path("/Users/mdeachaval/labs/machaval/mulesoft/anypoint-public-api-specs/portal")
13+
STYLES_CSS = Path("/Users/mdeachaval/labs/machaval/mulesoft/anypoint-public-api-specs/scripts/portal_generator/assets/styles.css")
14+
15+
def extract_classes_from_html(html_path):
16+
"""Extract all CSS classes from an HTML file."""
17+
classes = set()
18+
with open(html_path, 'r', encoding='utf-8') as f:
19+
content = f.read()
20+
# Find all class attributes
21+
class_matches = re.findall(r'class="([^"]*)"', content)
22+
for match in class_matches:
23+
# Split multiple classes
24+
classes.update(match.split())
25+
return classes
26+
27+
def get_css_selector_classes(selector):
28+
"""Extract class names from a CSS selector."""
29+
# Remove pseudo-classes and pseudo-elements
30+
selector = re.sub(r'::[a-z-]+', '', selector)
31+
selector = re.sub(r':[a-z-]+(\([^)]*\))?', '', selector)
32+
33+
# Extract classes (.classname)
34+
classes = re.findall(r'\.([a-zA-Z0-9_-]+)', selector)
35+
return set(classes)
36+
37+
def parse_css_rules(css_content):
38+
"""Parse CSS and return list of (selector, rule_content) tuples."""
39+
rules = []
40+
41+
# Remove comments
42+
css_content = re.sub(r'/\*.*?\*/', '', css_content, flags=re.DOTALL)
43+
44+
# Find all CSS rules (selector { properties })
45+
# This regex matches selectors and their corresponding rule blocks
46+
pattern = r'([^{}]+)\{([^{}]*)\}'
47+
matches = re.finditer(pattern, css_content)
48+
49+
for match in matches:
50+
selector = match.group(1).strip()
51+
properties = match.group(2).strip()
52+
53+
# Skip empty rules
54+
if not properties:
55+
continue
56+
57+
# Skip @-rules (media queries, keyframes, etc.)
58+
if selector.startswith('@'):
59+
continue
60+
61+
rules.append((selector, properties))
62+
63+
return rules
64+
65+
def main():
66+
print("Analyzing HTML files...")
67+
68+
# Get classes from homepage template
69+
homepage_template = Path("/Users/mdeachaval/labs/machaval/mulesoft/anypoint-public-api-specs/scripts/portal_generator/templates/homepage.html")
70+
homepage_classes = extract_classes_from_html(homepage_template)
71+
print(f"Found {len(homepage_classes)} unique classes in homepage template")
72+
73+
# Get classes from all other template files (detail pages, skills, operations, etc.)
74+
templates_dir = Path("/Users/mdeachaval/labs/machaval/mulesoft/anypoint-public-api-specs/scripts/portal_generator/templates")
75+
detail_classes = set()
76+
for html_file in templates_dir.rglob("*.html"):
77+
if html_file.name != "homepage.html":
78+
detail_classes.update(extract_classes_from_html(html_file))
79+
80+
print(f"Found {len(detail_classes)} unique classes in non-homepage templates")
81+
82+
# Find homepage-only classes
83+
homepage_only = homepage_classes - detail_classes
84+
print(f"Found {len(homepage_only)} classes used ONLY in homepage")
85+
print(f"\nHomepage-only classes:")
86+
for cls in sorted(homepage_only):
87+
print(f" .{cls}")
88+
89+
# Read CSS file
90+
print(f"\nReading {STYLES_CSS}...")
91+
with open(STYLES_CSS, 'r', encoding='utf-8') as f:
92+
css_content = f.read()
93+
94+
# Parse CSS rules
95+
css_rules = parse_css_rules(css_content)
96+
print(f"Found {len(css_rules)} CSS rules")
97+
98+
# Find rules that ONLY use homepage-only classes
99+
homepage_only_rules = []
100+
for selector, properties in css_rules:
101+
selector_classes = get_css_selector_classes(selector)
102+
103+
# If selector has classes and ALL of them are homepage-only
104+
if selector_classes and selector_classes.issubset(homepage_only):
105+
homepage_only_rules.append((selector, properties))
106+
107+
print(f"\nFound {len(homepage_only_rules)} rules that use ONLY homepage-specific classes")
108+
109+
# Generate homepage-specific CSS
110+
homepage_css = "/* Homepage-specific styles */\n"
111+
homepage_css += "/* This file contains CSS rules used ONLY in index.html */\n\n"
112+
113+
for selector, properties in homepage_only_rules:
114+
# Clean up properties - normalize whitespace
115+
props_lines = [line.strip() for line in properties.split('\n') if line.strip()]
116+
formatted_props = '\n '.join(props_lines)
117+
homepage_css += f"{selector} {{\n {formatted_props}\n}}\n\n"
118+
119+
# Write to homepage.css
120+
output_path = STYLES_CSS.parent / "homepage.css"
121+
with open(output_path, 'w', encoding='utf-8') as f:
122+
f.write(homepage_css)
123+
124+
print(f"\nWrote homepage-specific CSS to: {output_path}")
125+
print(f"Total rules extracted: {len(homepage_only_rules)}")
126+
127+
if __name__ == "__main__":
128+
main()

0 commit comments

Comments
 (0)