This code will generate the table of content from the heading tag used on the single page or post. Refer to the comments on the code to customize the code.
Add the below code to the functions.php file
// declare a function and pass the $content as an argument function insert_table_of_contents($content) { // used to determine the location of the // table of contents when $fixed_location is set to false $html_comment = "<!--insert-toc-->"; // checks if $html_comment exists in $content $comment_found = strpos($content, $html_comment) ? true : false; // set to true to insert the table of contents in a fixed location // set to false to replace $html_comment with $table_of_contents $fixed_location = true; // return the $content if // $comment_found and $fixed_location are false if (!$fixed_location && !$comment_found) { return $content; } // exclude the table of contents from all pages // other exclusion options include: // in_category($id) // has_term($term_name) // is_single($array) // is_author($id) if (is_page()) { return $content; } // regex to match all HTML heading elements 2-6 $regex = "~(<h([2-6]))(.*?>(.*)<\/h[2-6]>)~"; // preg_match_all() searches the $content using $regex patterns and // returns the results to $heading_results[] // // $heading_results[0][] contains all matches in full // $heading_results[1][] contains '<h2-6' // $heading_results[2][] contains '2-6' // $heading_results[3][] contains '>heading title</h2-6> // $heading_results[4][] contains the title text preg_match_all($regex, $content, $heading_results); // return $content if less than 3 heading exist in the $content $num_match = count($heading_results[0]); if($num_match < 3) { return $content; } // declare local variable $link_list = ""; // loop through $heading_results for ($i = 0; $i < $num_match; ++ $i) { // rebuild heading elements to have anchors $new_heading = $heading_results[1][$i] . " id='$i' " . $heading_results[3][$i]; // find original heading elements that don't have anchors $old_heading = $heading_results[0][$i]; // search the $content for $old_heading and replace with $new_heading $content = str_replace($old_heading, $new_heading, $content); // generate links for each heading element // each link points to an anchor $link_list .= "<li class='heading-level-" . $heading_results[2][$i] . "'><a href='#$i'>" . $heading_results[4][$i] . "</a></li>"; } // opening nav tag $start_nav = "<nav class='table-of-content' id='ez-toc-container'>"; // closing nav tag $end_nav = "</nav>"; // title $title = "<h2>Outlines of Contents</h2>"; // wrap links in '<ul>' element $link_list = "<ul>" . $link_list . "</ul>"; // piece together the table of contents $table_of_contents = $start_nav . $title . $link_list . $end_nav; // if $fixed_location is true and // $comment_found is false // insert the table of contents at a fixed location if($fixed_location && !$comment_found) { // location of first paragraph $first_paragraph = strpos($content, '</p>', 0) + 4; // location of second paragraph $second_paragraph = strpos($content, '</p>', $first_p_pos); // insert $table_of_contents after $second_paragraph return substr_replace($content, $table_of_contents, $second_paragraph + 4 , 0); } // if $fixed_location is false and // $comment_found is true else { // replace $html_comment with the $table_of_contents return str_replace($html_comment, $table_of_contents, $content); } } // pass the function to the content add_filter hook add_filter('the_content', 'insert_table_of_contents');