61963e72f5
- Moved image: field from outside to inside YAML frontmatter (50 files) - Converted all 56 non-WebP images to proper WebP format via ImageMagick - Fixed Python shebangs for portability - Updated source fields in 2 Task 3 recipes
129 lines
4.2 KiB
Python
129 lines
4.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Fix the broken YAML frontmatter: move image field inside YAML, and convert non-WebP images."""
|
|
|
|
import re, subprocess, sys
|
|
from pathlib import Path
|
|
|
|
WORKDIR = Path("/home/jbrechtel/recipes/.worktrees/recipe-images")
|
|
|
|
def fix_frontmatter(content: str) -> str:
|
|
"""Move image: field inside the YAML block if it's outside."""
|
|
# Check if image: is before the opening ---
|
|
lines = content.split('\n')
|
|
|
|
# Find the first --- line
|
|
first_hr = -1
|
|
for i, line in enumerate(lines):
|
|
if line.strip() == '---':
|
|
first_hr = i
|
|
break
|
|
|
|
if first_hr <= 0:
|
|
return content # No frontmatter or image is at first line
|
|
|
|
# Check if the line just before the first --- has image:
|
|
if first_hr > 0 and lines[first_hr - 1].startswith('image:'):
|
|
# Extract the image line
|
|
img_line = lines[first_hr - 1]
|
|
# Remove it from before ---
|
|
del lines[first_hr - 1]
|
|
# Now first_hr is one index less (or same if we deleted the line before)
|
|
# Find the closing ---
|
|
closing_hr = -1
|
|
for i in range(first_hr, len(lines)):
|
|
if lines[i].strip() == '---':
|
|
closing_hr = i
|
|
break
|
|
|
|
if closing_hr > first_hr:
|
|
# Insert image line before the closing ---
|
|
lines.insert(closing_hr, img_line)
|
|
else:
|
|
# Insert after the closing --- (fallback)
|
|
lines.insert(first_hr + 1, img_line)
|
|
|
|
return '\n'.join(lines)
|
|
|
|
|
|
def fix_all_frontmatter():
|
|
"""Fix frontmatter for all .cook files."""
|
|
fixed = 0
|
|
for f in sorted(WORKDIR.glob("*.cook")):
|
|
content = f.read_text(encoding="utf-8")
|
|
fixed_content = fix_frontmatter(content)
|
|
if fixed_content != content:
|
|
f.write_text(fixed_content, encoding="utf-8")
|
|
print(f" Fixed: {f.name}")
|
|
fixed += 1
|
|
print(f"\nFixed {fixed} files with mis-placed image fields")
|
|
return fixed
|
|
|
|
|
|
def convert_images():
|
|
"""Convert non-WebP images to actual WebP format."""
|
|
converted = 0
|
|
for img in sorted(WORKDIR.glob("recipe-images/*.webp")):
|
|
mime = subprocess.run(
|
|
["file", "-b", "--mime-type", str(img)],
|
|
capture_output=True, text=True
|
|
).stdout.strip()
|
|
|
|
if mime != "image/webp":
|
|
print(f" Converting {img.name} (mime: {mime})")
|
|
# Use temp file to avoid corruption
|
|
tmp = img.with_suffix(".webp.tmp")
|
|
result = subprocess.run(
|
|
["convert", str(img), str(tmp)],
|
|
capture_output=True, text=True
|
|
)
|
|
if result.returncode == 0 and tmp.exists():
|
|
tmp.replace(img)
|
|
print(f" Converted successfully")
|
|
converted += 1
|
|
else:
|
|
print(f" Convert failed: {result.stderr}")
|
|
|
|
print(f"\nConverted {converted} images to proper WebP")
|
|
return converted
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("=== Fixing YAML frontmatter ===")
|
|
fix_all_frontmatter()
|
|
|
|
print("\n=== Converting image formats ===")
|
|
convert_images()
|
|
|
|
# Final check
|
|
print("\n=== Final verification ===")
|
|
bad = 0
|
|
for f in sorted(WORKDIR.glob("*.cook")):
|
|
content = f.read_text(encoding="utf-8")
|
|
# Check if image: is between --- markers
|
|
if "image:" in content:
|
|
# Find the opening ---
|
|
parts = content.split('---', 2)
|
|
if len(parts) >= 3:
|
|
if "image:" not in parts[1]:
|
|
print(f" STILL BROKEN: {f.name}")
|
|
bad += 1
|
|
|
|
if bad == 0:
|
|
print(" All files have image: inside YAML block ✅")
|
|
|
|
webp_count = 0
|
|
non_webp_count = 0
|
|
for img in sorted(WORKDIR.glob("recipe-images/*.webp")):
|
|
mime = subprocess.run(
|
|
["file", "-b", "--mime-type", str(img)],
|
|
capture_output=True, text=True
|
|
).stdout.strip()
|
|
if mime == "image/webp":
|
|
webp_count += 1
|
|
else:
|
|
non_webp_count += 1
|
|
if non_webp_count <= 5:
|
|
print(f" NOT WEBP: {img.name} ({mime})")
|
|
|
|
print(f" WebP images: {webp_count}, Non-WebP: {non_webp_count}")
|