Este hook para WordPress soluciona el problema de accesibilidad de los enlaces de varias maneras:
Características principales:
- Detección automática: Identifica enlaces que solo contienen imágenes o íconos sin texto descriptivo
- Generación de descripciones: Crea automáticamente descripciones basadas en:
- Patrones de URL (servicios, contacto, redes sociales, etc.)
- Contenido interno del enlace (alt text de imágenes)
- Clases CSS del elemento
- Atributo aria-label: Agrega automáticamente el atributo
aria-label
con texto descriptivo - Estilos de accesibilidad: Incluye CSS para mejorar el foco visual y marcar enlaces externos
Cómo usar:
- Instalación: Copia el código al
functions.php
de tu child theme - Personalización: Modifica el array
$url_patterns
para agregar más patrones específicos de tu sitio - Shortcode: Usa
[accessible_link]
para crear enlaces accesibles manualmente:-
[accessible_link url="/servicios" description="Ver todos nuestros servicios"] <img src="arrow.png" alt="flecha"> [/accessible_link]
-
- Función PHP: Usa
accessible_link()
en templates:-
echo accessible_link('/contacto', '<i class="icon-arrow"></i>', 'Ir a página de contacto');
El hook procesará automáticamente el contenido y mejorará la accesibilidad de enlaces existentes sin modificar tu HTML actual, solucionando el problema que muestras en la imagen de la auditoría de accesibilidad.
-
Orden de prioridad para generar nombres:
- Texto visible del enlace – Si hay texto real en el enlace, lo usa directamente
- Alt text de imágenes – Si contiene una imagen con alt descriptivo
- Atributo title – De cualquier elemento interno
- Atributos data-* – Como data-title, data-label, data-text
- Patrones de URL – Solo como respaldo para URLs conocidas
- Slug de la URL – Convierte el slug en texto legible (ej: «peritaje-informatico» → «Peritaje Informático»)
La función extract_link_text()
es especialmente inteligente porque:
- Extrae texto real de spans, divs, párrafos dentro del enlace
- Ignora elementos vacíos o que solo contienen símbolos
- Busca texto en atributos como placeholder y value
- Como último recurso, extrae cualquier texto visible
Y extract_text_from_url()
convierte URLs como /analisis-forense/
en «Análisis Forense» de forma automática.
/** * Hook para mejorar la accesibilidad de los enlaces agregando nombres descriptivos * Agregar al functions.php del child theme */ // Hook para procesar el contenido y mejorar los enlaces add_filter('the_content', 'improve_link_accessibility'); add_filter('widget_text', 'improve_link_accessibility'); function improve_link_accessibility($content) { // Procesar enlaces que solo contienen imágenes o íconos $content = preg_replace_callback( '/<a([^>]*href="([^"]*)"[^>]*)>(\s*<[^>]*>\s*)*<\/a>/i', 'add_accessible_link_text', $content ); return $content; } function add_accessible_link_text($matches) { $full_link = $matches[0]; $link_attributes = $matches[1]; $url = $matches[2]; $inner_content = $matches[3]; // Si el enlace ya tiene texto descriptivo, no modificarlo if (preg_match('/[a-zA-Z]{3,}/', strip_tags($inner_content))) { return $full_link; } // Si ya tiene aria-label o title descriptivo, no modificarlo if (preg_match('/aria-label\s*=\s*["\'][^"\']{10,}["\']/', $link_attributes) || preg_match('/title\s*=\s*["\'][^"\']{10,}["\']/', $link_attributes)) { return $full_link; } // Generar texto descriptivo basado en la URL o contexto $descriptive_text = generate_link_description($url, $inner_content); if ($descriptive_text) { // Agregar aria-label con el texto descriptivo $new_attributes = $link_attributes . ' aria-label="' . esc_attr($descriptive_text) . '"'; return '<a' . $new_attributes . '>' . $inner_content . '</a>'; } return $full_link; } function generate_link_description($url, $inner_content = '') { if (!empty($inner_content)) { // 1. Primero intentar extraer texto visible del enlace $text_content = extract_link_text($inner_content); if (!empty($text_content)) { return trim($text_content); } // 2. Si contiene una imagen, usar el alt text if (preg_match('/<img[^>]*alt\s*=\s*["\']([^"\']+)["\'][^>]*>/i', $inner_content, $alt_match)) { $alt_text = trim($alt_match[1]); if (!empty($alt_text) && $alt_text !== 'image' && strlen($alt_text) > 2) { return $alt_text; } } // 3. Buscar title en elementos internos if (preg_match('/title\s*=\s*["\']([^"\']{3,})["\']/', $inner_content, $title_match)) { return trim($title_match[1]); } // 4. Buscar data-* attributes que puedan tener descripción if (preg_match('/data-(?:title|label|text)\s*=\s*["\']([^"\']{3,})["\']/', $inner_content, $data_match)) { return trim($data_match[1]); } } // 5. Como último recurso, usar patrones de URL $url_patterns = array( '/peritaje-informatico/i' => 'Peritaje Informático', '/analisis-forense/i' => 'Análisis Forense', '/contacto/i' => 'Contacto', '/servicios/i' => 'Servicios', '/blog/i' => 'Blog', '/portfolio/i' => 'Portfolio', '/sobre-nosotros|about/i' => 'Sobre Nosotros', '/telefono|phone|tel:/i' => 'Teléfono', '/email|mailto:/i' => 'Email', '/facebook\.com/i' => 'Facebook', '/twitter\.com|x\.com/i' => 'Twitter', '/linkedin\.com/i' => 'LinkedIn', '/instagram\.com/i' => 'Instagram', '/youtube\.com/i' => 'YouTube', '/whatsapp/i' => 'WhatsApp', ); foreach ($url_patterns as $pattern => $description) { if (preg_match($pattern, $url)) { return $description; } } // 6. Extraer texto del slug de la URL $url_text = extract_text_from_url($url); if (!empty($url_text)) { return $url_text; } return 'Enlace'; } // Función auxiliar para extraer texto visible del contenido del enlace function extract_link_text($content) { // Remover scripts y estilos $content = preg_replace('/<(script|style)[^>]*>.*?<\/\1>/si', '', $content); // Extraer texto de elementos con contenido textual $text_elements = array(); // Buscar spans, divs, p, etc. con texto if (preg_match_all('/>([^<]{3,})</i', $content, $matches)) { foreach ($matches[1] as $text) { $cleaned_text = trim(strip_tags($text)); if (strlen($cleaned_text) > 2 && !preg_match('/^[\s\W]*$/', $cleaned_text)) { $text_elements[] = $cleaned_text; } } } // Buscar texto en atributos placeholder, value, etc. if (preg_match('/(?:placeholder|value)\s*=\s*["\']([^"\']{3,})["\']/', $content, $attr_match)) { $text_elements[] = trim($attr_match[1]); } // Devolver el primer texto válido encontrado if (!empty($text_elements)) { return $text_elements[0]; } // Como último recurso, extraer cualquier texto visible $plain_text = trim(strip_tags($content)); if (strlen($plain_text) > 2 && !preg_match('/^[\s\W]*$/', $plain_text)) { return $plain_text; } return ''; } // Función auxiliar para extraer texto legible de una URL function extract_text_from_url($url) { $parsed_url = parse_url($url); $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; // Extraer la última parte del path (slug) $path_parts = array_filter(explode('/', $path)); if (!empty($path_parts)) { $slug = end($path_parts); // Limpiar el slug y convertirlo en texto legible $slug = preg_replace('/\.[^.]+$/', '', $slug); // remover extensión $slug = str_replace(array('-', '_'), ' ', $slug); $slug = ucwords(trim($slug)); if (strlen($slug) > 2) { return $slug; } } return ''; } // Hook adicional para enlaces específicos en el tema add_action('wp_head', 'add_custom_link_styles'); function add_custom_link_styles() { ?> <style> /* Mejorar visualmente los enlaces para accesibilidad */ a:focus { outline: 2px solid #005fcc; outline-offset: 2px; } /* Indicador visual para enlaces externos */ a[href^="http"]:not([href*="<?php echo home_url(); ?>"])::after { content: " ↗"; font-size: 0.8em; opacity: 0.7; } </style> <?php } // Función para agregar manualmente aria-label a enlaces específicos function accessible_link($url, $content, $description = '', $class = '') { $aria_label = $description ? 'aria-label="' . esc_attr($description) . '"' : ''; $class_attr = $class ? 'class="' . esc_attr($class) . '"' : ''; return '<a href="' . esc_url($url) . '" ' . $aria_label . ' ' . $class_attr . '>' . $content . '</a>'; } // Shortcode para crear enlaces accesibles add_shortcode('accessible_link', 'accessible_link_shortcode'); function accessible_link_shortcode($atts, $content = null) { $atts = shortcode_atts(array( 'url' => '#', 'description' => '', 'class' => '', 'target' => '' ), $atts); $target_attr = $atts['target'] ? 'target="' . esc_attr($atts['target']) . '"' : ''; $aria_label = $atts['description'] ? 'aria-label="' . esc_attr($atts['description']) . '"' : ''; $class_attr = $atts['class'] ? 'class="' . esc_attr($atts['class']) . '"' : ''; return '<a href="' . esc_url($atts['url']) . '" ' . $aria_label . ' ' . $class_attr . ' ' . $target_attr . '>' . do_shortcode($content) . '</a>'; } /** * Uso del shortcode: * [accessible_link url="https://ejemplo.com" description="Visitar página de servicios"]Contenido del enlace[/accessible_link] */