Automatically add a table of contents from the headings in your posts.
add_filter( 'the_content', function ( $content ) {
// This snippet requires the DOMDocument class to be available.
if ( ! class_exists( 'DOMDocument' ) ) {
return $content;
}
if ( !is_single() || !in_the_loop() || !is_main_query() ) {
return $content;
}
$dom = new DOMDocument();
$load_content = mb_convert_encoding( $content, 'HTML-ENTITIES', 'UTF-8' );
if ( empty( $load_content ) ) {
return $content;
}
@$dom->loadHTML( $load_content );
$xpath = new DOMXPath( $dom );
$headings = $xpath->query( '//h2 | //h3' );
// Let's loop through all the headings and add them to the table of contents.
$headings_list = '<ul class="table-of-contents">';
foreach ( $headings as $heading ) {
$heading_id = $heading->getAttribute( 'id' );
if ( empty( $heading_id ) ) {
// Generate a heading id and add it to the heading.
$old_heading = $heading->C14N();
$heading_id = sanitize_title( $heading->nodeValue );
$heading->setAttribute( 'id', $heading_id );
$content = str_replace( $old_heading, $heading->C14N(), $content );
}
$heading_text = $heading->nodeValue;
$headings_list .= '<li><a href="#' . $heading_id . '">' . $heading_text . '</a></li>';
}
$headings_list .= '</ul>';
$content = $headings_list . $content;
return $content;
} );