69 lines
2.2 KiB
PHP
69 lines
2.2 KiB
PHP
<?php
|
|
if ( ! defined( 'ABSPATH' ) ) exit;
|
|
|
|
class WMW_TOC {
|
|
|
|
/**
|
|
* Generate TOC and add anchor IDs to headings in content.
|
|
* Returns array: ['content' => ..., 'toc' => ...]
|
|
*/
|
|
public static function process( $content ) {
|
|
if ( empty( $content ) ) return array( 'content' => $content, 'toc' => '' );
|
|
|
|
$headings = array();
|
|
$counter = array();
|
|
|
|
// Add IDs to h2, h3, h4
|
|
$content = preg_replace_callback(
|
|
'/<(h[234])([^>]*)>(.*?)<\/h[234]>/si',
|
|
function( $matches ) use ( &$headings, &$counter ) {
|
|
$tag = $matches[1];
|
|
$attrs = $matches[2];
|
|
$text = wp_strip_all_tags( $matches[3] );
|
|
$slug = sanitize_title( $text );
|
|
|
|
// Make unique
|
|
if ( isset( $counter[ $slug ] ) ) {
|
|
$counter[ $slug ]++;
|
|
$slug .= '-' . $counter[ $slug ];
|
|
} else {
|
|
$counter[ $slug ] = 0;
|
|
}
|
|
|
|
$headings[] = array(
|
|
'level' => (int) substr( $tag, 1 ),
|
|
'id' => $slug,
|
|
'text' => $text,
|
|
);
|
|
|
|
return "<{$tag}{$attrs} id=\"{$slug}\">{$matches[3]}</{$tag}>";
|
|
},
|
|
$content
|
|
);
|
|
|
|
if ( empty( $headings ) || count( $headings ) < 2 ) {
|
|
return array( 'content' => $content, 'toc' => '' );
|
|
}
|
|
|
|
// Build TOC HTML
|
|
$toc = '<div class="wmw-toc">';
|
|
$toc .= '<div class="wmw-toc__title"><span>' . __( 'Inhalt', 'wp-multi-wiki' ) . '</span><button class="wmw-toc__toggle" aria-label="TOC ausklappen">▼</button></div>';
|
|
$toc .= '<ol class="wmw-toc__list">';
|
|
|
|
$prev_level = 2;
|
|
foreach ( $headings as $h ) {
|
|
if ( $h['level'] > $prev_level ) {
|
|
$toc .= '<ol class="wmw-toc__sub">';
|
|
} elseif ( $h['level'] < $prev_level ) {
|
|
$toc .= '</ol>';
|
|
}
|
|
$toc .= '<li><a href="#' . esc_attr( $h['id'] ) . '">' . esc_html( $h['text'] ) . '</a></li>';
|
|
$prev_level = $h['level'];
|
|
}
|
|
|
|
$toc .= '</ol></div>';
|
|
|
|
return array( 'content' => $content, 'toc' => $toc );
|
|
}
|
|
}
|