currentPostId = get_the_ID() ?: 0; } public function render(Component $component): string { $data = $component->getData(); if (!$this->isEnabled($data)) { return ''; } $autoGenerate = $data['config']['auto_generate'] ?? true; $tocItems = $autoGenerate ? $this->generateTocFromContent($data) : $this->getManualItems($data); if (empty($tocItems)) { return ''; } $componentId = $component->getId(); $customStyles = $this->generateCustomStyles($componentId, $data['styles'] ?? []); $stickyClass = ($data['visibility']['sticky'] ?? true) ? 'sidebar-sticky' : ''; $mobileClass = !($data['visibility']['show_on_mobile'] ?? false) ? 'd-none d-lg-block' : ''; $title = $data['config']['title'] ?? 'Tabla de Contenido'; $maxHeight = $data['config']['max_height'] ?? 'calc(100vh - 400px)'; $offsetTop = $data['config']['offset_top'] ?? 100; ob_start(); ?>

    2 ? 'toc-level-' . $level : ''; ?>
post_content)) { return []; } $headingLevels = $data['config']['heading_levels'] ?? ['h2', 'h3']; $content = apply_filters('the_content', $post->post_content); $dom = new DOMDocument(); libxml_use_internal_errors(true); $dom->loadHTML('' . $content); libxml_clear_errors(); $xpath = new DOMXPath($dom); $xpathQuery = implode(' | ', array_map(function($level) { return '//' . $level; }, $headingLevels)); $headings = $xpath->query($xpathQuery); if ($headings->length === 0) { return []; } $tocItems = []; $headingCounter = []; foreach ($headings as $heading) { $tagName = strtolower($heading->tagName); $level = intval(substr($tagName, 1)); $text = trim($heading->textContent); if (empty($text)) { continue; } $existingId = $heading->getAttribute('id'); $anchor = !empty($existingId) ? $existingId : $this->generateAnchorId($text, $headingCounter); $tocItems[] = [ 'text' => $text, 'anchor' => $anchor, 'level' => $level ]; } return $tocItems; } private function getManualItems(array $data): array { return $data['manual_items']['items'] ?? []; } private function generateAnchorId(string $text, array &$counter): string { $id = strtolower($text); $id = remove_accents($id); $id = preg_replace('/[^a-z0-9]+/', '-', $id); $id = trim($id, '-'); $baseId = $id; $count = 1; while (isset($counter[$id])) { $id = $baseId . '-' . $count; $count++; } $counter[$id] = true; return $id; } private function generateCustomStyles(string $componentId, array $styles): string { if (empty($styles)) { return ''; } $css = []; if (isset($styles['background_color'])) { $css[] = "#$componentId.toc-container { background: {$styles['background_color']}; }"; } if (isset($styles['border_color'])) { $css[] = "#$componentId.toc-container { border-color: {$styles['border_color']}; }"; } if (isset($styles['title_color'])) { $css[] = "#$componentId.toc-container h4 { color: {$styles['title_color']}; }"; } if (isset($styles['link_color'])) { $css[] = "#$componentId .toc-link { color: {$styles['link_color']}; }"; } if (isset($styles['link_hover_color'])) { $css[] = "#$componentId .toc-link:hover { color: {$styles['link_hover_color']}; }"; } if (isset($styles['active_border_color'])) { $css[] = "#$componentId .toc-link.active { border-left-color: {$styles['active_border_color']}; }"; } if (isset($styles['active_bg_color'])) { $css[] = "#$componentId .toc-link.active { background-color: {$styles['active_bg_color']}; }"; } return implode("\n", $css); } public function supports(string $componentType): bool { return $componentType === 'table-of-contents'; } }