diff --git a/Inc/apu-tables.php b/Inc/apu-tables.php index f26b5d7e..f8faf5df 100644 --- a/Inc/apu-tables.php +++ b/Inc/apu-tables.php @@ -18,6 +18,10 @@ if (!defined('ABSPATH')) { * Detecta tablas con el atributo data-apu y las envuelve * con la clase .analisis para aplicar estilos específicos. * + * TAMBIÉN agrega clases a filas especiales (section-header, subtotal-row, total-row) + * del lado del servidor para PREVENIR CLS. Anteriormente esto se hacía con JS + * en apu-tables-auto-class.js, lo cual causaba CLS de 0.692 en Lab Data. + * * @param string $content El contenido del post * @return string El contenido procesado */ @@ -43,10 +47,116 @@ function roi_process_apu_tables($content) { return '
' . $table . '
'; }, $content); + // Procesar TODAS las tablas APU (dentro de .analisis o .desglose) para agregar clases a filas + // Esto reemplaza la lógica de apu-tables-auto-class.js para prevenir CLS + $content = roi_add_apu_row_classes($content); + return $content; } add_filter('the_content', 'roi_process_apu_tables', 20); +/** + * Agrega clases CSS a filas especiales de tablas APU del lado del servidor + * + * IMPORTANTE: Esta función reemplaza apu-tables-auto-class.js para PREVENIR CLS. + * La manipulación del DOM con JS después de DOMContentLoaded causa Layout Shift. + * + * Detecta y clasifica: + * - section-header: Material, Mano de Obra, Herramienta, Equipo + * - subtotal-row: Filas que empiezan con "Suma de" o "Subtotal" + * - total-row: Costo Directo, Total + * + * @param string $content HTML del contenido + * @return string HTML con clases agregadas a filas + */ +function roi_add_apu_row_classes($content) { + // Solo procesar si hay tablas APU + if (strpos($content, 'class="analisis"') === false && strpos($content, 'class="desglose"') === false) { + return $content; + } + + // Patrones para detectar tipos de fila (basado en contenido de segunda celda) + $section_headers = [ + 'Material', + 'Mano de Obra', + 'Herramienta', + 'Equipo', + 'MATERIAL', + 'MANO DE OBRA', + 'HERRAMIENTA', + 'EQUIPO', + ]; + + $total_patterns = [ + 'Costo Directo', + 'COSTO DIRECTO', + 'Costo directo', + 'Total', + 'TOTAL', + ]; + + // Procesar filas dentro de + // Patrón: capturar con sus atributos y contenido + $content = preg_replace_callback( + '/]*)>(.*?)<\/tr>/is', + function($matches) use ($section_headers, $total_patterns) { + $tr_attrs = $matches[1]; + $tr_content = $matches[2]; + + // Si ya tiene clase especial, no modificar + if (preg_match('/class\s*=\s*["\'][^"\']*(?:section-header|subtotal-row|total-row)/', $tr_attrs)) { + return $matches[0]; + } + + // Extraer texto de la segunda celda + if (!preg_match('/]*>.*?<\/td>\s*]*>(.*?)<\/td>/is', $tr_content, $cell_match)) { + return $matches[0]; // No hay segunda celda + } + + $cell_text = trim(strip_tags($cell_match[1])); + + // Determinar clase a agregar + $class_to_add = ''; + + // Verificar section-header + if (in_array($cell_text, $section_headers, true)) { + $class_to_add = 'section-header'; + } + // Verificar subtotal-row + elseif (stripos($cell_text, 'suma de ') === 0 || stripos($cell_text, 'subtotal ') === 0) { + $class_to_add = 'subtotal-row'; + } + // Verificar total-row + elseif (in_array($cell_text, $total_patterns, true)) { + $class_to_add = 'total-row'; + } + + // Si no hay clase que agregar, retornar sin modificar + if (empty($class_to_add)) { + return $matches[0]; + } + + // Agregar clase al + if (preg_match('/class\s*=\s*["\']([^"\']*)["\']/', $tr_attrs)) { + // Ya tiene atributo class, agregar a las clases existentes + $tr_attrs = preg_replace( + '/class\s*=\s*["\']([^"\']*)["\']/', + 'class="$1 ' . $class_to_add . '"', + $tr_attrs + ); + } else { + // No tiene class, agregar el atributo + $tr_attrs = ' class="' . $class_to_add . '"' . $tr_attrs; + } + + return '' . $tr_content . ''; + }, + $content + ); + + return $content; +} + /** * Shortcode: [apu_table] * Permite envolver tablas manualmente con la clase .analisis diff --git a/Inc/enqueue-scripts.php b/Inc/enqueue-scripts.php index ca1cfaed..e413c78c 100644 --- a/Inc/enqueue-scripts.php +++ b/Inc/enqueue-scripts.php @@ -578,26 +578,29 @@ add_action('wp_enqueue_scripts', 'roi_enqueue_apu_tables_styles', 5); // Priorit /** * Enqueue APU Tables auto-class JavaScript * - * Este script detecta automáticamente filas especiales en tablas .desglose y .analisis - * y les agrega las clases CSS correspondientes (section-header, subtotal-row, total-row) + * DESHABILITADO: Este script causaba CLS de 0.692 en Lab Data. + * La manipulación del DOM con JS después de DOMContentLoaded causa Layout Shift. * - * Issue #132 + * La lógica ha sido movida a PHP server-side en Inc/apu-tables.php + * @see roi_add_apu_row_classes() + * + * Issue #132 - Original implementation */ -function roi_enqueue_apu_tables_autoclass_script() { - // APU Tables Auto-Class JS - wp_enqueue_script( - 'roi-apu-tables-autoclass', - get_template_directory_uri() . '/Assets/js/apu-tables-auto-class.js', - array(), - ROI_VERSION, - array( - 'in_footer' => true, - 'strategy' => 'defer', - ) - ); -} - -add_action('wp_enqueue_scripts', 'roi_enqueue_apu_tables_autoclass_script', 15); +// function roi_enqueue_apu_tables_autoclass_script() { +// // APU Tables Auto-Class JS +// wp_enqueue_script( +// 'roi-apu-tables-autoclass', +// get_template_directory_uri() . '/Assets/js/apu-tables-auto-class.js', +// array(), +// ROI_VERSION, +// array( +// 'in_footer' => true, +// 'strategy' => 'defer', +// ) +// ); +// } +// add_action('wp_enqueue_scripts', 'roi_enqueue_apu_tables_autoclass_script', 15); +// DISABLED: Moved to server-side PHP to prevent CLS /** * Enqueue CTA Box Sidebar styles (Issue #36)