parser = $parser; $this->anchor_generator = $anchor_generator; $this->builder = $builder; $this->injector = $injector; $this->config = $config; } public function generate(string $content): array { $this->anchor_generator->reset(); $headings = $this->parser->extract($content); if (empty($headings)) { return $this->emptyResult($content); } $headings = $this->parser->filterByLevels($headings, $this->config->getHeadingLevels()); $headings = $this->parser->excludeByPatterns($headings, $this->config->getExcludePatterns()); $headings = $this->parser->removeEmpty($headings); if (count($headings) < $this->config->getMinHeadings()) { return $this->emptyResult($content); } $headings = $this->enrichHeadings($headings); $toc_html = $this->buildTocHtml($headings); $content_with_anchors = $this->injector->injectAnchors($content, $headings); $final_content = $this->injector->injectToc($content_with_anchors, $toc_html, $this->config->getPosition()); return [ 'content' => $final_content, 'toc_html' => $toc_html, 'headings_count' => count($headings), ]; } private function enrichHeadings(array $headings): array { return array_map(function($heading) { $clean_text = $this->parser->cleanText($heading['text']); $anchor = $this->anchor_generator->generate($clean_text); return array_merge($heading, [ 'clean_text' => $clean_text, 'anchor' => $anchor, ]); }, $headings); } private function buildTocHtml(array $headings): string { $list_html = $this->builder->build($headings); if (empty($list_html)) { return ''; } return $this->wrapToc($list_html); } private function wrapToc(string $list_html): string { $theme = esc_attr($this->config->getTheme()); $list_type = esc_attr($this->config->shouldNumberList() ? 'numbered' : 'bulleted'); $hierarchy_class = esc_attr($this->config->shouldShowHierarchy() ? 'hierarchical' : 'flat'); $hidden_class = $this->config->getInitialState() === 'hide' ? ' toc-hidden' : ''; $html = '
'; if ($this->config->shouldShowTitle() || $this->config->shouldShowToggle()) { $html .= '
'; if ($this->config->shouldShowTitle()) { $html .= '

' . esc_html($this->config->getTitle()) . '

'; } if ($this->config->shouldShowToggle()) { $expanded = $this->config->getInitialState() === 'show' ? 'true' : 'false'; $html .= ''; } $html .= '
'; } $html .= '
'; $html .= $list_html; $html .= '
'; $html .= '
'; return $html; } private function emptyResult(string $content): array { return [ 'content' => $content, 'toc_html' => '', 'headings_count' => 0, ]; } }