Fix sad eye highlight injection with robust parsing and debug logs

- Replace fragile regex with index-based string manipulation
- Find opening tag first, then locate closing tag by position
- Add DEV-only debug logging for eye detection and injection
- Log whether blobbi-eye groups are found and matched
- Log eye positions and water fill generation
- Should fix sad highlights not appearing in blobbi-eye groups
This commit is contained in:
filemon
2026-03-27 00:35:24 -03:00
parent 2d9ff34ded
commit c907779b3c
+63 -19
View File
@@ -633,31 +633,66 @@ function generateSadHighlightElements(eye: EyePosition): string {
* This ensures sad highlights move with eye tracking and blink properly.
*/
export function applySadEyeHighlights(svgText: string, eyes: EyePosition[]): string {
if (import.meta.env.DEV) {
console.log('[Sad Eyes] Starting applySadEyeHighlights with', eyes.length, 'eyes');
console.log('[Sad Eyes] SVG contains blobbi-eye:', svgText.includes('blobbi-eye'));
}
// Process each eye - find blobbi-eye groups and modify them
for (const eye of eyes) {
// Find the blobbi-eye group for this side
const eyeGroupRegex = new RegExp(
`(<g\\s+class="blobbi-eye\\s+blobbi-eye-${eye.side}"[^>]*>)([\\s\\S]*?)(</g>)`,
// Find the opening tag of the blobbi-eye group for this side
// Match pattern: <g ...class="...blobbi-eye-left..."...>
const openTagRegex = new RegExp(
`<g[^>]*class="[^"]*blobbi-eye-${eye.side}[^"]*"[^>]*>`,
'i'
);
const match = svgText.match(eyeGroupRegex);
if (match) {
const [fullMatch, openTag, content, closeTag] = match;
const openMatch = svgText.match(openTagRegex);
if (import.meta.env.DEV) {
console.log(`[Sad Eyes] Eye ${eye.side}: open tag match =`, !!openMatch);
if (openMatch) {
console.log(`[Sad Eyes] Eye ${eye.side}: open tag =`, openMatch[0].substring(0, 80));
}
}
if (openMatch && openMatch.index !== undefined) {
const openTagStart = openMatch.index;
const openTagEnd = openTagStart + openMatch[0].length;
// Hide original white highlights (small white circles) by adding opacity="0"
// Original highlights are typically: <circle ... fill="white" ... />
const modifiedContent = content.replace(
/(<circle[^>]*fill="white"[^>]*)(\/?>)/gi,
'$1 opacity="0" $2'
);
// Find the matching closing </g> tag
// The blobbi-eye group should not contain nested <g> tags,
// so we can find the first </g> after the content
const afterOpenTag = svgText.substring(openTagEnd);
const closeTagIndex = afterOpenTag.indexOf('</g>');
// Add sad highlights at the end of the group content
const sadHighlights = generateSadHighlightElements(eye);
const newContent = modifiedContent + sadHighlights;
// Replace in SVG
svgText = svgText.replace(fullMatch, openTag + newContent + closeTag);
if (closeTagIndex !== -1) {
const content = afterOpenTag.substring(0, closeTagIndex);
const absoluteCloseStart = openTagEnd + closeTagIndex;
if (import.meta.env.DEV) {
console.log(`[Sad Eyes] Eye ${eye.side}: found group content, length =`, content.length);
}
// Hide original white highlights (small white circles) by adding opacity="0"
const modifiedContent = content.replace(
/(<circle[^>]*fill="white"[^>]*)(\/?>)/gi,
'$1 opacity="0" $2'
);
// Add sad highlights at the end of the group content
const sadHighlights = generateSadHighlightElements(eye);
const newContent = modifiedContent + sadHighlights;
if (import.meta.env.DEV) {
console.log(`[Sad Eyes] Eye ${eye.side}: injecting sad highlights`);
}
// Reconstruct the SVG with modified content
svgText = svgText.substring(0, openTagEnd) + newContent + svgText.substring(absoluteCloseStart);
}
} else if (import.meta.env.DEV) {
console.log(`[Sad Eyes] Eye ${eye.side}: NO MATCH for blobbi-eye-${eye.side}`);
}
}
@@ -727,12 +762,21 @@ export function applyEmotion(svgText: string, emotion: BlobbiEmotion): string {
// Generate sad eye effects (watery eyes with repositioned highlights)
if (config.pupilModification?.wateryEyes && eyes.length > 0) {
if (import.meta.env.DEV) {
console.log('[Sad Eyes] Applying sad eye effects. Eyes detected:', eyes.length);
eyes.forEach(e => console.log(` - ${e.side} eye at (${e.cx}, ${e.cy}) radius=${e.radius}`));
}
// 1. Apply sad highlights INTO the blobbi-eye groups (for tracking/blinking)
// This also hides the original highlights
svgText = applySadEyeHighlights(svgText, eyes);
// 2. Add blue water fill as overlay (on eye white, doesn't need to track)
overlays.push(generateSadEyeWaterFill(eyes));
const waterFill = generateSadEyeWaterFill(eyes);
if (import.meta.env.DEV) {
console.log('[Sad Eyes] Water fill generated, length:', waterFill.length);
}
overlays.push(waterFill);
}
// Generate tears