['title'=>'单独设置', 'type'=>'checkbox', 'value'=>1, 'label'=>'文章列表和编辑页面可以单独设置是否显示文章目录以及显示到第几级。'], 'depth' => ['title'=>'显示层级', 'type'=>'select', 'value'=>6, 'options'=> wpjam_fill(range(2, 6), fn($v)=> 'H'.$v)], 'position' => ['title'=>'显示位置', 'type'=>'select', 'value'=>'content', 'options'=>['content'=>'显示在文章内容前面', 'shortcode'=>'使用[toc]插入内容中', 'function'=>'显示在侧边栏/调用函数wpjam_get_toc()显示']], ]+(current_theme_supports('style', 'toc') ? [] : [ 'css' => ['title'=>'显示样式', 'type'=>'textarea', 'description'=>'也可以将相关的样式代码复制主题的对应文件中,点击这里获取文章目录的默认的 CSS'] ]); } public static function output($wrap=true){ $toc = is_singular() ? (string)self::get_arg('toc') : ''; return $toc && $wrap ? '
'."\n".'文章目录'."\n".$toc.'
'."\n" : $toc; } public static function filter_content($content){ $depth = self::get_setting('individual', 1) ? (int)get_post_meta(get_the_ID(), 'toc_depth', true) : 0; $depth = $depth ?: self::get_setting('depth', 6); if($depth && $depth != -1){ $i = 0; $stack = []; $output = $toc = ''; $index = str_contains($content, '[toc]'); $tag = $index ? 'ol' : 'ul'; $parts = preg_split('#(]*)>(.*?))#is', $content, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); while($i < count($parts)){ $part = $parts[$i]; if(str_starts_with($part, '= 1 && $part[2] <= $depth){ $level = (int)$parts[$i+1]; $attr = $parts[$i+2] ? shortcode_parse_atts($parts[$i+2]) : []; if(!str_contains($attr['class'] ?? '', 'toc-noindex')){ if(empty($attr['id'])){ $attr['id'] = 'toc_'.($i+1); } if($stack){ if($level > array_last($stack)){ $toc .= "\n<".$tag.">\n"; $output .= $index ? '
'."\n" : ''; }else{ while($level <= array_last($stack)){ $toc .= "\n"; if($level < array_pop($stack)){ $toc .= "\n"; $output .= $index ? "
\n" : ''; } } } } $stack[] = $level; $toc .= '
  • '.trim(strip_tags($parts[$i+3])).''; } $output .= wpjam_tag('h'.$level, $attr, $parts[$i+3]); $i += 4; }else{ $output .= $part; $i += 1; } } if($stack){ $content = implode([ !$index && self::get_setting('position', 'content') == 'content' ? '[toc]' : '', $output, $index ? str_repeat("\n", count($stack)-1) : '' ]); self::update_arg('toc', "<".$tag.">\n".$toc.str_repeat("
  • \n\n", count($stack))); } } return str_replace('[toc]', self::output(), $content); } public static function add_hooks(){ wpjam_register_widget('wpjam-toc', 'WPJAM - 文章目录', [ 'classname' => 'widget_toc', 'fields' => ['title' => ['type'=>'text', 'before'=>'列表标题:', 'class'=>'medium-text']], 'widget' => fn()=> self::output(false) ]); wpjam_once('maybe', 'the_content', fn($content)=> !doing_filter('get_the_excerpt') && wpjam_is('single', get_the_ID()) ? self::filter_content($content) : null, 11); if($css = self::get_setting('css')){ wpjam_hook('wp_head', fn()=> is_singular() && !current_theme_supports('style', 'toc') && wpjam_echo('')); } self::get_setting('individual', 1) && wpjam_register_post_option('wpjam-toc', [ 'title' => '文章目录', 'context' => 'side', 'list_table' => true, 'post_type' => fn($type)=> is_post_type_viewable($type) && post_type_supports($type, 'editor'), 'fields' => ['toc_depth' => [ 'title' => '层级:', 'type' => 'select', 'show_in_rest' => ['type'=>'integer'], 'default' => 0, 'options' => [0=>'默认']+wpjam_fill(range(2, 6), fn($v)=> 'H'.$v)+[-1=>'不显示'] ]] ]); } } wpjam_register_option('wpjam-toc', [ 'model' => 'WPJAM_Toc', 'title' => '文章目录', 'menu_page' => ['tab_slug'=>'toc', 'plugin_page'=>'wpjam-posts', 'summary'=> __FILE__] ]); function wpjam_get_toc(){ return WPJAM_Toc::output(); }