feat: Implement recursive component extraction in the build script, unwrapping structural frames like showcases.

This commit is contained in:
Ho Ngoc Hai
2026-01-31 20:30:31 +07:00
parent 468d93a8b3
commit c93fdf3192
2 changed files with 2127 additions and 2528 deletions

View File

@@ -306,6 +306,33 @@ class PencilBuilder:
print(f"📊 Total frames: {len(monolithic['children'])}")
print(f"🎨 Design tokens: {len(variables)}")
def _extract_components_recursive(self, children: List[Dict], gathered: List[Dict]) -> None:
"""Recursively find components, unwrapping structural frames"""
for child in children:
# 1. If reusable, ALWAYS keep it (it's explicitly a component)
if child.get('reusable'):
gathered.append(child)
continue
# 2. Check if it's a structural wrapper (Showcase, Section)
name = child.get('name', '')
is_frame = child.get('type') == 'frame'
is_structural = 'showcase' in name.lower() or 'section' in name.lower()
if is_frame and is_structural:
# Unwrap and recurse
self._extract_components_recursive(child.get('children', []), gathered)
elif is_frame:
# 3. Valid Candidate (Frame that isn't structural/showcase)
# It might be a group of buttons (e.g. "buttonExamples") or an actual component candidate
# For now, we keep it as a potential component
gathered.append(child)
else:
# 4. Primitives (Text, Rect, etc.) at this level
# If they are loose in a Showcase, we probably ignore them (decorations like Titles)
# If they are inside a Kept Frame, they were preserved in step 3.
pass
def build_library(self, output_path: str = None) -> None:
"""Build merged component library from Atomic Design files"""
print("🔨 Building Component Library")
@@ -340,22 +367,14 @@ class PencilBuilder:
for pen_file in sorted(dir_path.glob('*.pen')):
with open(pen_file, 'r') as f:
data = json.load(f)
# Extract children (components/showcases)
file_children = data.get('children', [])
# If the file contains a "Showcase" frame wrapping everything,
# we ideally want to extract the inner reusable components if we want a clean library.
# BUT, users might want the showcase organization in the library too.
# Let's flatten showcases for the library so components are cleaner?
# Actually, keeping showcases/groups is better for Pencil's sidebar organization.
# Use recursive extraction
file_components = []
self._extract_components_recursive(data.get('children', []), file_components)
# Update: Ensure all top-level children have unique IDs if possible?
# Pencil IDs are UUIDs mostly, should be fine.
components.extend(file_children)
total_found += len(file_children)
print(f" ✓ Added contents of {pen_file.name}")
components.extend(file_components)
total_found += len(file_components)
print(f" ✓ Added {len(file_components)} components from {pen_file.name}")
# 3. Create Library File
library_file = {

File diff suppressed because it is too large Load Diff