js 生成标题目录树

文章目录 (?) [+]

    重构博客主题时(Compass V2.0 Rebirth)写的一段代码,记录一下...

    效果如下:

    /**
     * Compass Theme For Journey
     *
     * @abstract
     * @version     2.0
     * @date        2020/01/03 16:47
     * @author      Wildlife <admin@lanseyujie.com>
     * @link        https://lanseyujie.com
     * @copyright   Copyright(c) 2014-2021, lanseyujie.com
     */
    function buildToc(contentId, listId) {
        let content = document.getElementById(contentId);
        if (!content) {
            return
        }
        let tree = content.querySelectorAll('*'),
            ele = document.getElementById(listId),
            tags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
            lastLevel = 1,
            // 初始化一个有序列表
            rootList = document.createElement('ol'),
            // 当前的根列表
            list = rootList;
    
        rootList.setAttribute('class', 'toc-list');
        ele.append(rootList);
    
        tree.forEach(function (node, index) {
            // 当前 nodeName 存在于 H 标签列表;H 标签是否存在有效标题
            if (tags.indexOf(node.nodeName.toLowerCase()) !== -1 && node.textContent.length > 0) {
                // 标记该标题的 id hash 以便跳转
                node.setAttribute('id', 'toc-' + index);
    
                // 获取 H 标签的级别
                let level = node.nodeName.slice(1),
                    // 为该 H 标题创建索引 <li level=1><a href="#toc-1">title</a></li>
                    li = document.createElement('li'),
                    a = document.createElement('a');
                // 标记索引级别
                li.setAttribute('data-level', level);
                a.setAttribute('href', '#toc-' + index);
                a.setAttribute('title', node.textContent)
                a.textContent = node.textContent;
                li.appendChild(a);
    
                if (index === 0 || lastLevel === level) {
                    // 将大标题插入根列表
                    list.appendChild(li);
                } else if (lastLevel < level) {
                    if (list.hasChildNodes()) {
                        // 当前较上一标题为小标题则创建子列表,并插入索引
                        let ol = document.createElement('ol');
                        ol.setAttribute('class', 'toc-list');
                        ol.appendChild(li);
                        list.appendChild(ol);
                        // 更新当前的根列表
                        list = ol;
                    } else {
                        // 上层根列表不存在索引则直接插入
                        list.appendChild(li);
                    }
                } else if (lastLevel > level) {
                    // 当前较上一标题为大标题则创建子列表,则获取差几级
                    let diff = lastLevel - level;
                    if (diff < 6) {
                        // 以当前根列表为基准,向父层遍历到所属层级根列表
                        let tmpList = list;
                        for (let i = 1; i < 6; i++) {
                            if (tmpList.parentNode) {
                                tmpList = tmpList.parentNode;
                                // 判断是否与该列表内索引层级一致 253,242如果返回
                                if (tmpList.firstElementChild.getAttribute('data-level') === level || i === diff) {
                                    break;
                                }
                            }
                        }
                        tmpList.appendChild(li);
                        list = tmpList;
                    } else {
                        // 增强校错
                        rootList.appendChild(li);
                        list = rootList;
                    }
                }
                lastLevel = level;
            }
        });
    
        if (rootList.hasChildNodes()) {
            ele.parentElement.classList.remove('hidden')
        }
    }


    本文标题:js 生成标题目录树
    本文链接:https://lanseyujie.com/post/table-of-contents-generator-in-javascript.html
    版权声明:本文使用「署名-非商业性使用-相同方式共享」创作共享协议,转载或使用请遵守署名协议。
    点赞 0 分享 0