Files
wehub-resource-sync 8cb1f9f479
Publish SDK (PyPI) / publish (push) Has been cancelled
Publish SDK (npm) / publish (@aionui/officecli-sdk) (push) Has been cancelled
SDK smoke / smoke (windows-latest) (push) Has been cancelled
Publish SDK (npm) / publish (@officecli/officecli-sdk) (push) Has been cancelled
Publish SDK (npm) / publish (@officecli/sdk) (push) Has been cancelled
Publish SDK (npm) / publish (officecli-sdk) (push) Has been cancelled
SDK smoke / smoke (macos-latest) (push) Has been cancelled
SDK smoke / smoke (ubuntu-latest) (push) Has been cancelled
Skill parity / diff (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:09:29 +08:00

364 lines
12 KiB
Bash
Executable File

#!/bin/bash
# Morph PPT Helper Functions
# Purpose: Simplify morph workflow by bundling common operations with built-in verification
# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# ============================================
# morph_clone_slide: Clone slide and set transition
# ============================================
# Usage: morph_clone_slide <deck.pptx> <from_slide_num> <to_slide_num>
# Example: morph_clone_slide deck.pptx 1 2
#
# What it does:
# 1. Clone the source slide
# 2. Automatically set transition=morph
# 3. List all shapes for ghosting reference
# 4. Verify transition was set correctly
morph_clone_slide() {
local deck=$1
local from_slide=$2
local to_slide=$3
echo -e "${BLUE}📋 Cloning slide $from_slide$to_slide...${NC}"
officecli add "$deck" '/' --from "/slide[$from_slide]"
echo -e "${BLUE}⚡ Setting morph transition...${NC}"
officecli set "$deck" "/slide[$to_slide]" --prop transition=morph
echo -e "${BLUE}📊 Listing shapes for ghosting reference:${NC}"
officecli get "$deck" "/slide[$to_slide]" --depth 1
# Verify transition was set
echo -e "${BLUE}🔍 Verifying transition...${NC}"
local trans=$(officecli get "$deck" "/slide[$to_slide]" --json 2>/dev/null | grep '"transition": "morph"')
if [ -z "$trans" ]; then
echo -e "${RED}❌ ERROR: Transition not set on slide $to_slide!${NC}"
echo -e "${RED} This slide will not have morph animation.${NC}"
exit 1
else
echo -e "${GREEN}✅ Transition verified on slide $to_slide${NC}"
fi
echo ""
}
# ============================================
# morph_ghost_content: Ghost multiple shapes at once
# ============================================
# Usage: morph_ghost_content <deck.pptx> <slide_num> <shape_idx1> [shape_idx2] [shape_idx3] ...
# Example: morph_ghost_content deck.pptx 2 7 8 9
#
# What it does:
# 1. Move specified shapes to x=36cm (off-screen)
# 2. Show progress for each shape
# 3. Verify all shapes were ghosted
morph_ghost_content() {
local deck=$1
local slide=$2
shift 2
local shapes=("$@")
if [ ${#shapes[@]} -eq 0 ]; then
echo -e "${YELLOW}⚠️ No shapes to ghost${NC}"
return 0
fi
echo -e "${BLUE}👻 Ghosting ${#shapes[@]} content shape(s) on slide $slide...${NC}"
for shape_idx in "${shapes[@]}"; do
officecli set "$deck" "/slide[$slide]/shape[$shape_idx]" --prop x=36cm 2>/dev/null
if [ $? -eq 0 ]; then
echo -e "${GREEN} ✓ Ghosted shape[$shape_idx]${NC}"
else
echo -e "${RED} ✗ Failed to ghost shape[$shape_idx]${NC}"
fi
done
echo -e "${GREEN}✅ Ghosting complete${NC}"
echo ""
}
# ============================================
# morph_verify_slide: Verify slide has correct setup
# ============================================
# Usage: morph_verify_slide <deck.pptx> <slide_num>
# Example: morph_verify_slide deck.pptx 2
#
# What it does:
# 1. Check if transition=morph is set
# 2. Check for unghosted content from previous slide (by '#sN-' prefix)
# 3. Check for duplicate content (same text at same position) - BACKUP DETECTION
# 4. Report any issues found
#
# TWO DETECTION METHODS:
#
# Method 1: Name-based detection (Primary)
# - Checks if shapes with '#sN-' prefix are ghosted
# - REQUIRES correct naming: '#s1-title', '#s2-card', etc.
# - Fast and accurate when naming is correct
#
# Method 2: Duplicate detection (Backup insurance)
# - Checks if adjacent slides have identical text at identical positions
# - Works even if naming is wrong (e.g., 's1-title' instead of '#s1-title')
# - Catches cases where content wasn't ghosted OR naming is incorrect
# - Ignores ghost zone (x=36cm) duplicates (those are expected)
#
# WHY TWO METHODS?
# If agents forget '#' prefix, Method 1 fails but Method 2 still catches the problem!
morph_verify_slide() {
local deck=$1
local slide=$2
echo -e "${BLUE}🔍 Verifying slide $slide...${NC}"
local has_error=0
# Check transition
local trans=$(officecli get "$deck" "/slide[$slide]" --json 2>/dev/null | grep '"transition": "morph"')
if [ -z "$trans" ]; then
echo -e "${RED} ❌ Missing transition=morph${NC}"
echo -e "${RED} Without this, slide will not animate!${NC}"
has_error=1
else
echo -e "${GREEN} ✅ Transition OK${NC}"
fi
# Check for unghosted content from previous slide
local prev_slide=$((slide - 1))
if [ $prev_slide -ge 1 ]; then
# Use JSON output for reliable parsing
local shapes_json=$(officecli get "$deck" "/slide[$slide]" --json 2>/dev/null)
# Use python to parse JSON and find unghosted content
local unghosted_check
unghosted_check=$(printf '%s' "$shapes_json" | python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
def check_children(children, prev_slide):
unghosted = []
for child in children:
name = child.get('format', {}).get('name', '')
x = child.get('format', {}).get('x', '')
path = child.get('path', '')
# Check if this shape has previous slide's content prefix
if f'#s{prev_slide}-' in name:
# Check if it's NOT ghosted (x != 36cm)
if x != '36cm':
unghosted.append(f\"{path}: name={name}, x={x}\")
# Recursively check children
if 'children' in child:
unghosted.extend(check_children(child['children'], prev_slide))
return unghosted
if 'children' in data.get('data', {}):
unghosted = check_children(data['data']['children'], $prev_slide)
if unghosted:
for item in unghosted:
print(item)
sys.exit(1)
sys.exit(0)
except Exception as e:
print(f'[helper] parse error: {e}', file=sys.stderr)
sys.exit(2)
")
local python_exit=$?
if [ $python_exit -eq 1 ] && [ -n "$unghosted_check" ]; then
echo -e "${YELLOW} ⚠️ Warning: Found unghosted content from slide $prev_slide:${NC}"
echo "$unghosted_check" | sed 's/^/ /'
echo -e "${YELLOW} These shapes should be ghosted to x=36cm${NC}"
has_error=1
else
echo -e "${GREEN} ✅ No unghosted content detected${NC}"
fi
fi
# Additional check: Detect duplicate content between adjacent slides
# (Catches cases where content shapes are missing #sN- prefix)
if [ $prev_slide -ge 1 ]; then
local prev_json=$(officecli get "$deck" "/slide[$prev_slide]" --json 2>/dev/null)
local curr_json="$shapes_json"
local duplicates
duplicates=$(python3 -c "
import sys, json
try:
prev_data = json.loads('''$prev_json''')
curr_data = json.loads('''$curr_json''')
def extract_textboxes(data, slide_num):
boxes = []
def walk(children):
for child in children:
if child.get('type') == 'textbox':
name = child.get('format', {}).get('name', '')
text = child.get('text', '').strip()
x = child.get('format', {}).get('x', '')
y = child.get('format', {}).get('y', '')
path = child.get('path', '')
# Skip empty text and very short text
if not text or len(text) < 6:
continue
# Clean name (remove !! prefix if present)
clean_name = name.replace('!!', '') if name else ''
# Skip pure scene actors (common keywords)
scene_keywords = ['ring', 'dot', 'line', 'circle', 'rect', 'slash',
'accent', 'actor', 'star', 'triangle', 'diamond']
is_scene = any(kw in clean_name.lower() for kw in scene_keywords)
# Include if:
# 1. Name contains 'sN-' pattern (likely content even if missing #)
# 2. Not a pure scene actor
has_slide_pattern = any(f's{i}-' in clean_name for i in range(1, 20))
if has_slide_pattern or not is_scene:
boxes.append({
'path': path,
'name': name,
'text': text[:50], # First 50 chars
'x': x,
'y': y
})
if 'children' in child:
walk(child['children'])
if 'children' in data.get('data', {}):
walk(data['data']['children'])
return boxes
prev_boxes = extract_textboxes(prev_data, $prev_slide)
curr_boxes = extract_textboxes(curr_data, $slide)
duplicates = []
for curr in curr_boxes:
for prev in prev_boxes:
# Check if text and position are identical
if (curr['text'] == prev['text'] and
curr['x'] == prev['x'] and
curr['y'] == prev['y']):
# Skip if both are already in ghost position (x=36cm)
# (It's normal for ghosted content to be at same position)
if curr['x'] != '36cm':
duplicates.append(f\"{curr['path']}: text='{curr['text']}...', pos=({curr['x']},{curr['y']})\")
break
if duplicates:
for dup in duplicates:
print(dup)
sys.exit(1)
sys.exit(0)
except Exception as e:
print(f'[helper] parse error: {e}', file=sys.stderr)
sys.exit(2)
")
local dup_exit=$?
if [ $dup_exit -eq 1 ] && [ -n "$duplicates" ]; then
echo -e "${YELLOW} ⚠️ Warning: Found duplicate content from slide $prev_slide (same text at same position):${NC}"
echo "$duplicates" | sed 's/^/ /'
echo -e "${YELLOW} This might indicate:${NC}"
echo -e "${YELLOW} 1. Content shapes missing '#sN-' prefix (can't detect for ghosting)${NC}"
echo -e "${YELLOW} 2. Forgot to ghost previous slide's content${NC}"
echo -e "${YELLOW} 3. Forgot to add new content for this slide${NC}"
has_error=1
fi
fi
if [ $has_error -eq 0 ]; then
echo -e "${GREEN}✅ Slide $slide verification passed${NC}"
else
echo -e "${RED}❌ Slide $slide has issues - see above${NC}"
return 1
fi
echo ""
}
# ============================================
# morph_final_check: Verify entire deck
# ============================================
# Usage: morph_final_check <deck.pptx>
# Example: morph_final_check deck.pptx
#
# What it does:
# 1. Check all slides (2+) have transition=morph
# 2. Summary report of any issues
morph_final_check() {
local deck=$1
echo -e "${BLUE}🎯 Final deck verification...${NC}"
echo ""
# Get total slides
local total_slides=$(officecli view "$deck" outline 2>/dev/null | head -1 | grep -oE '[0-9]+' | head -1 || echo "0")
if [ "$total_slides" -eq 0 ]; then
echo -e "${RED}❌ No slides found in deck${NC}"
return 1
fi
echo "Total slides: $total_slides"
echo ""
local error_count=0
# Check each slide starting from slide 2
for ((i=2; i<=total_slides; i++)); do
if ! morph_verify_slide "$deck" "$i"; then
((error_count++))
fi
done
echo ""
echo "========================================="
if [ $error_count -eq 0 ]; then
echo -e "${GREEN}✅ All slides verified successfully!${NC}"
echo -e "${GREEN} Your morph animations should work correctly.${NC}"
return 0
else
echo -e "${RED}❌ Found issues in $error_count slide(s)${NC}"
echo -e "${RED} Please fix the issues above before delivering.${NC}"
return 1
fi
}
# Show usage if called directly
if [ "${BASH_SOURCE[0]}" == "${0}" ]; then
echo "Morph PPT Helper Functions"
echo ""
echo "Usage: source morph-helpers.sh"
echo ""
echo "Available functions:"
echo " morph_clone_slide <deck> <from> <to> - Clone slide and set transition"
echo " morph_ghost_content <deck> <slide> <idx...> - Ghost multiple shapes"
echo " morph_verify_slide <deck> <slide> - Verify slide setup"
echo " morph_final_check <deck> - Verify entire deck"
echo ""
echo "Example:"
echo " source morph-helpers.sh"
echo " morph_clone_slide deck.pptx 1 2"
echo " morph_ghost_content deck.pptx 2 7 8"
echo " morph_verify_slide deck.pptx 2"
fi