Created
July 28, 2012 09:46
-
-
Save turtlepod/3192682 to your computer and use it in GitHub Desktop.
Genbu Table Of Content Shortcode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* Genbu Table Of Content Shortcode | |
* use [gtoc] to generate shortcode | |
* | |
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without | |
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
* | |
* Based on (credit) : | |
* WP TOC by Brendon Boshell http://infinity-infinity.com/ | |
* | |
* @package Genbu TOC | |
* @since 1.0.0 | |
*/ | |
add_action('after_setup_theme','genbu_toc_setup'); | |
function genbu_toc_setup(){ | |
/* Genbu Table of Content. */ | |
add_shortcode( "gtoc", "genbu_toc_shortcode_toc" ); | |
add_action( "the_content", "genbu_toc_the_content" ); | |
//remove_filter('the_content', 'wptexturize'); | |
} | |
// open a nested list | |
function genbu_toc_open_level($new, $cur, $first, $type) { | |
$levels = $new - $cur; | |
$out = ""; | |
for($i = $cur; $i < $new; $i++) { | |
$level = $i - $first + 2; | |
if(($level % 2) == 0) | |
$out .= "<{$type} class='toc-even level-{$level}'>\n"; | |
else | |
$out .= "<{$type} class='toc-odd level-{$level}'>\n"; | |
} | |
return $out; | |
} | |
// close the list | |
function genbu_toc_close_level( $new, $cur, $first, $type ) { | |
$out = ""; | |
for($i = $cur; $i > $new; $i--) | |
$out .= "</{$type}>\n"; | |
return $out; | |
} | |
$wptoc_used_names = array(); | |
function genbu_toc_get_unique_name($heading) { | |
global $wptoc_used_names; | |
$n = strip_tags($heading); | |
$n = str_replace('"', '', strip_tags($heading)); | |
$n = str_replace(" ", "_", $heading); | |
$n = preg_replace("#[^A-Za-z0-9\-_\:\.]#", "", $n); | |
$n = preg_replace("#^[^A-Za-z]*?([A-Za-z])#", "$1", $n); | |
if (isset($wptoc_used_names[$n])) { | |
$wptoc_used_names[$n]++; | |
$n .= "_" . $wptoc_used_names[$n]; | |
$wptoc_used_names[$n] = 0; | |
} else { | |
$wptoc_used_names[$n] = 0; | |
} | |
return $n; | |
} | |
function genbu_toc_unique_names_reset() { | |
global $wptoc_used_names; | |
$wptoc_used_names = array(); | |
return true; | |
} | |
function genbu_toc_shortcode_toc($attribs) { | |
global $post; | |
if (is_singular() && !is_attachment()){ | |
genbu_toc_unique_names_reset(); | |
// REMOVE PLUGIN OPTION | |
$attribs = shortcode_atts( | |
array( | |
"depth" => 20, | |
"listtype" => 'ul', | |
"title" => __('Table Of Content:','tamatebako') | |
), | |
$attribs); | |
extract($attribs); | |
$depth = $depth ? $depth : 20; | |
$list_type = $listtype ? $listtype : "ul"; | |
$title = $title ? $title : __('Table Of Content:','tamatebako'); | |
// get the post | |
// don't consider stuff in <pre>s | |
$content = preg_replace("#<pre.*?>(.|\n|\r)*?<\/pre>#i", "", $post->post_content); | |
$lowest_heading = 1; | |
// calculate the lowest value heading (ie <hN> where N is a number) | |
// in the post | |
for($i = 1; $i <= 6; $i++) | |
if( preg_match("#<h" . $i . "#i", $content) ) { | |
$lowest_heading = $i; | |
break; | |
} | |
// maximum | |
$max_heading = $lowest_heading + $depth - 1; | |
// find page separation points | |
$next_pages = array(); | |
preg_match_all("#<\!--nextpage-->#i", $content, $next_pages, PREG_OFFSET_CAPTURE); | |
$next_pages = $next_pages[0]; | |
// get all headings in post | |
$headings = array(); | |
preg_match_all("#<h([1-6])>(.*?)</h[1-6]>#i", $content, $headings, PREG_OFFSET_CAPTURE); | |
$cur_level = $lowest_heading; | |
$out = '<div id="table-of-content">'; | |
if ($title) | |
$out .= '<div id="toc-title">' . $title . '</div>'; | |
$out .= genbu_toc_open_level($lowest_heading, $lowest_heading-1, $lowest_heading, $list_type); | |
$first = true; | |
$tabs = 1; | |
// headings... | |
foreach($headings[2] as $i => $heading) { | |
$level = $headings[1][$i][0]; // <hN> | |
if($level > $max_heading) // heading too deep | |
continue; | |
if($level > $cur_level) { // this needs to be nested | |
$out .= str_repeat("\t", $tabs+1) . genbu_toc_open_level( $level, $cur_level, $lowest_heading, $list_type ); | |
$first = true; | |
$tabs += 2; | |
} | |
if(!$first) | |
$out .= str_repeat("\t", $tabs) . "</li>\n"; | |
$first = false; | |
if($level < $cur_level) { // jump back up from nest | |
$out .= str_repeat("\t", $tabs-1) . genbu_toc_close_level( $level, $cur_level, $lowest_heading, $list_type ); | |
$tabs -= 2; | |
} | |
$name = genbu_toc_get_unique_name($heading[0]); | |
$page_num = 1; | |
$pos = $heading[1]; | |
// find the current page | |
foreach($next_pages as $p) { | |
if($p[1] < $pos) | |
$page_num++; | |
} | |
// fix error if heading link overlap / not hieraricaly correct | |
if ($tabs+1 > 0) { | |
$tabs = $tabs; | |
} | |
else { | |
$tabs = 0; | |
} | |
// output the Contents item with link to the heading. Uses | |
// unique ID based on the $prefix variable. | |
if($page_num != 1) | |
$out .= str_repeat("\t", $tabs) . "<li>\n" . str_repeat("\t", $tabs+1) . "<a href=\"?p=" . $post->ID . "&page=" . $page_num . "#" . esc_attr($name). "\">" . $heading[0] . "</a>\n"; | |
else | |
$out .= str_repeat("\t", $tabs) . "<li>\n" . str_repeat("\t", $tabs+1) . "<a href=\"#" . esc_attr($name). "\">" . $heading[0] . "</a>\n"; | |
$cur_level = $level; // set the current level we are at | |
} | |
if(!$first) | |
$out .= str_repeat("\t", $tabs) . "</li>\n"; | |
// close up the list | |
$out .= genbu_toc_close_level( 0, $cur_level, $lowest_heading, $list_type ); | |
$out .= "</div>\n"; | |
// return value to repalce the Shortcode | |
return $out; | |
} | |
} | |
function genbu_toc_heading_anchor($match) { | |
$name = genbu_toc_get_unique_name($match[2]); | |
return '<span id="' .esc_attr($name) . '">' . $match[0] . '</span>'; | |
} | |
function genbu_toc_the_content($content) { | |
genbu_toc_unique_names_reset(); | |
$out = preg_replace_callback("#<h([1-6])>(.*?)</h[1-6]>#i", "genbu_toc_heading_anchor", $content); | |
return $out; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment