Mặc định NukeViet chưa có tính năng tạo mục lục tự động. Bài viết này sẽ hướng dẫn các bạn thêm Mục lục Tự động cho NukeViet CMS.
Mục lục
Lưu ý: Để có thể hiển thị mục lục đúng và đẹp, chúng ta nên tạo các bài viết có cấu trúc chuẩn các thẻ heading (h1 - h6)
function mb_find_replace(&$find = false, &$replace = false, &$string = ''){ if (is_array($find) && is_array($replace) && $string) { // check if multibyte strings are supported if (function_exists('mb_strpos')) { for ($i = 0; $i < count($find); $i++) { $string = mb_substr($string, 0, mb_strpos($string, $find[$i])) . // everything befor $find $replace[$i] . // its replacement mb_substr($string, mb_strpos($string, $find[$i]) + mb_strlen($find[$i])) // everything after $find ; } } else { for ($i = 0; $i < count($find); $i++) { $string = substr_replace( $string, $replace[$i], strpos($string, $find[$i]), strlen($find[$i]) ); } } } return $string;}function url_anchor_target($title, &$array_anchors = []){ $title = strip_tags($title); $title = str_replace(array("\r", "\n", "\n\r", "\r\n"), ' ', $title); $title = str_replace('&', '', $title); // remove non alphanumeric chars $title = preg_replace('/[^a-zA-Z0-9 \-_]*/', '', $title); // convert spaces to _ $title = str_replace( array(' ', ' ', 'nbsp'), '_', $title ); // remove trailing - and _ $title = rtrim($title, '-_'); $title = strtolower($title); $title = str_replace('_', '-', $title); $title = str_replace('--', '-', $title); if (array_key_exists($title, $array_anchors)) { $array_anchors[$title]++; $title .= '-' . $array_anchors[$title]; } else $array_anchors[$title] = 1; return $title;}function get_title_target($title){ $title = strip_tags($title); $title = str_replace(array("\r", "\n", "\n\r", "\r\n"), ' ', $title); $title = str_replace('&', '', $title); return $title;}function build_hierarchy( &$matches ){ $current_depth = 100; // headings can't be larger than h6 but 100 as a default to be sure $html = ''; $numbered_items = array(); $numbered_items_min = null; // reset the internal collision collection $array_anchors = array(); // find the minimum heading to establish our baseline for ($i = 0; $i < count($matches); $i++) { if ( $current_depth > $matches[$i][2] ) $current_depth = (int)$matches[$i][2]; } $numbered_items[$current_depth] = 0; $numbered_items_min = $current_depth; for ($i = 0; $i < count($matches); $i++) { if ( $current_depth == (int)$matches[$i][2] ) $html .= '<li>'; // start lists if ( $current_depth != (int)$matches[$i][2] ) { for ($current_depth; $current_depth < (int)$matches[$i][2]; $current_depth++) { $numbered_items[$current_depth + 1] = 0; $html .= '<ul><li>'; } } // list item $html .= '<a href="#' . url_anchor_target( $matches[$i][0] ) . '">'; $html .= strip_tags($matches[$i][0]) . '</a>'; // end lists if ( $i != count($matches) - 1 ) { if ( $current_depth > (int)$matches[$i + 1][2] ) { for ($current_depth; $current_depth > (int)$matches[$i + 1][2]; $current_depth--) { $html .= '</li></ul>'; $numbered_items[$current_depth] = 0; } } if ( $current_depth == (int)@$matches[$i + 1][2] ) $html .= '</li>'; } else { // this is the last item, make sure we close off all tags for ($current_depth; $current_depth >= $numbered_items_min; $current_depth--) { $html .= '</li>'; if ( $current_depth != $numbered_items_min ) $html .= '</ul>'; } } } return $html;}
$news_contents['newscheckss'] = md5($news_contents['id'] . NV_CHECK_SESSION);
Thêm vào bên dưới đoạn sau
if (preg_match_all('/(<h([1-6]{1})[^>]*>).*<\/h\2>/msuU', $news_contents['bodyhtml'], $matches, PREG_SET_ORDER)) { $array_anchors = []; for ($i = 0; $i < count($matches); $i++) { $anchor = url_anchor_target($matches[$i][0], $array_anchors); $find[] = $matches[$i][0]; $replace[] = str_replace( array( $matches[$i][1], // start of heading '</h' . $matches[$i][2] . '>' // end of heading ), array( $matches[$i][1] . '<span id="' . $anchor . '">', '</span></h' . $matches[$i][2] . '>' ), $matches[$i][0] ); }}$news_contents['bodyhtml'] = mb_find_replace($find, $replace, $news_contents['bodyhtml']);$news_contents['toc'] = build_hierarchy($matches);
<div id="news-bodyhtml" class="bodytext margin-bottom-lg"> {DETAIL.bodyhtml}</div>
<!-- BEGIN: show_toc --> <div id="toc_container"> <p class="toc_title">Mục lục</p> <ul class="toc_list"> {DETAIL.toc} </ul> </div><!-- END: show_toc -->
đoạn code này mình không thêm vào bài viết được, bạn tải ở file đính kèm nhé!
if (! empty($news_contents['post_name'])) { $xtpl->parse('main.post_name');}
if (!empty($news_contents['toc'])) { $xtpl->parse('main.show_toc');}
#toc_container li,#toc_container ul { margin: 0; padding: 0}#toc_container.no_bullets li,#toc_container.no_bullets ul,#toc_container.no_bullets ul li,.toc_widget_list.no_bullets,.toc_widget_list.no_bullets li { background: 0 0; list-style-type: none; list-style: none}#toc_container.have_bullets li { padding-left: 12px}#toc_container ul ul { margin-left: 1.5em}#toc_container { background: #dff4ff; border-radius: 5px; margin-bottom: 1em; width: auto; display: table; position: relative;}#toc_container p.toc_title { text-align: center; font-weight: 900; margin: 0; padding: 10px 0 8px; font-family: "Roboto Slab", sans-serif; text-transform: uppercase; background: #f4f5f8; border-radius: 5px 5px 0 0;}#toc_container.toc_black p.toc_title { color: #aaa}#toc_container p.toc_title+ul.toc_list { padding: 10px 30px; overflow: hidden;}#toc_container a { text-decoration: none; text-shadow: none; color: #009ded; font-size: 15px; line-height: 15px;}#toc_container a:hover { color: #007bff;}.vuta_toc_readmore { text-align: center; cursor: pointer; position: absolute; z-index: 9999; bottom: 0; width: 100%; background: #fff;}.vuta_toc_readmore:before { height: 55px; margin-top: -45px; content: ""; background: -moz-linear-gradient( top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%); background: -webkit-linear-gradient( top, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%); background: linear-gradient( to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%); filter: progid: DXImageTransform.Microsoft.gradient( startColorstr='#ffffff00', endColorstr='#ffffff', GradientType=0); display: block;}.vuta_toc_readmore a { color: #222 !important; display: block; font-size: 13px !important; font-weight: 700;}.vuta_toc_readmore a:after { content: ""; width: 0; right: 0; border-top: 4px solid #222; border-left: 4px solid transparent; border-right: 4px solid transparent; display: inline-block; vertical-align: middle; margin: -2px 0 0 5px;}.vuta_toc_expand { text-align: center;}.vuta_toc_expand a { position: relative; color: #222 !important; font-size: 13px !important; font-weight: 700;}.vuta_toc_expand a:after { content: ""; width: 0; right: 0; border-bottom: 4px solid #222; border-left: 4px solid transparent; border-right: 4px solid transparent; display: inline-block; vertical-align: middle; margin: -2px 0 0 5px;}
Từ khóa được tìm kiếm nhiều nhất: Hướng dẫn thêm Mục lục Tự động cho NukeViet CMS
VUTA cung cấp hệ sinh thái giải pháp số toàn diện, giúp doanh nghiệp tối ưu vận hành, tăng trưởng bền vững và tạo lợi thế cạnh tranh.
Thiết kế riêng theo vận hành từng công ty: quản lý khách hàng, dự án, báo cáo doanh thu thời gian thực.
Xem chi tiết →Website doanh nghiệp & thương mại điện tử hiện đại, tối ưu hiển thị trên Google và AI Search.
Xem chi tiết →Đưa website lên top Google, giúp thương hiệu được ChatGPT, Gemini, Perplexity nhắc đến.
Xem chi tiết →Tạo, xác minh và tối ưu hồ sơ Google, tăng thứ hạng tìm kiếm gần bạn, quản lý đánh giá.
Xem chi tiết →Quảng cáo tìm kiếm, hiển thị & YouTube đúng khách hàng, tối ưu chi phí mỗi chuyển đổi.
Xem chi tiết →
Tác giả: Huỳnh Quốc Đạt