package browser import ( "fmt" "unicode/utf8" ) // CdpGetTextInFrame retorna el texto visible (innerText) del documento de un // iframe especifico, componiendo sobre CdpEvalInFrame con un mundo aislado CDP. // // Lee document.body.innerText (cae a document.documentElement.innerText si no // hay body), evitando parsear HTML crudo. Replica la politica de truncado de // CdpGetText: si maxBytes > 0 trunca al limite dado con corte rune-safe y añade // un sufijo con el total original en bytes; si maxBytes <= 0 no hay limite. // // Propaga los errores de CdpEvalInFrame (frame inexistente, contexto caducado) // envueltos con %w. func CdpGetTextInFrame(c *CDPConn, frameID string, maxBytes int) (string, error) { if c == nil { return "", fmt.Errorf("cdp get text in frame: conexion nula") } if frameID == "" { return "", fmt.Errorf("cdp get text in frame: frameID vacio") } const expr = `(document.body ? document.body.innerText : document.documentElement.innerText) || ""` text, err := CdpEvalInFrame(c, frameID, expr) if err != nil { return "", fmt.Errorf("cdp get text in frame: %w", err) } if maxBytes > 0 && len(text) > maxBytes { total := len(text) // Corte rune-safe: retrocede hasta encontrar un rune valido completo. cut := maxBytes for cut > 0 && !utf8.RuneStart(text[cut]) { cut-- } text = text[:cut] + fmt.Sprintf("\n…[truncado, total %d bytes]", total) } return text, nil }