美文网首页Node.js专题Node.jsKoa
cheerio制作markDown索引目录

cheerio制作markDown索引目录

作者: 92e6a2b361e8 | 来源:发表于2018-04-17 18:06 被阅读24次

    原文链接:Bougie的博客

    制作目录索引这种东西当然是放在前端方便。选择放在后端一是为了了解Node后端生态,掌握更多后端技术;二是因为公司实行前后端分离的方式开发,睾贵的JAVA后端经常啥也不做处理就返回一个row数据(甚至有时时间戳都不处理),对此有些无语。

    cheerio

    最终目标

    image
    1. 点击索引单项跳转到相应标题
    2. 大号标题包含小号标题,小号标题向右缩进
    3. 滚动页面时自动切换索引项active状态

    实现方法

    md转化为html

    const markDown = require('marked')
    markDown.setOptions({
        headerIds: false,
        highlight: function(code) {
            return require('highlight.js').highlightAuto(code).value;
        },
    })
    let html = markDown(data.content)
    

    cheerio生成索引

    const cheerio = require('cheerio')
    
    // decodeEntities防止中文转化为unicdoe
    const $ = cheerio.load(html,{decodeEntities: false})
    
    // 用hNum生成自定义id
    let hArr = [], highestLvl, hNum = 0
    $('h1, h2, h3, h4, h5, h6').each(function () {
        let id = `h${hNum}`
        hNum++
        $(this).attr('id', id)
        let lvl = $(this).get(0).tagName.substr(1)
        if(!highestLvl) highestLvl = lvl
        hArr.push({
            lvl: lvl - highestLvl + 1,
            content: $(this).html(),
            id: id
        })
    })
    Object.assign(data, {
        content: $.html,
        toc: hArr
    })
    

    前台展示

    if data && data.toc
        ul#toc-wrapper.toc-wrapper-transform
          each item in data.toc
            // 利用lvl判断偏移量
            li(class='toc-item text-elli', style=`padding-left: ${item.lvl * 15}px`, id=item.id)
              a(href=`#${item.id}`, title=item.content).text-elli= item.content
    

    页面滚动过自动切换active

    知道getBoundingClientRect API就好做了

    function tocToggle() {
        if($('.article-content').dom.length == 0) return
        let scrollArr = []
        document.querySelectorAll('.article-content h1, h2, h3, h4, h5, h6').forEach(i => {
            let elTop = Math.abs(i.getBoundingClientRect().top)
            scrollArr.push({
                el: i,
                top: elTop
            })
        })
        if(scrollArr.length == 0) return
        scrollArr = scrollArr.sort((a, b) => {
            return a.top - b.top
        })
        let activeId = $(scrollArr[0].el).attr('id')
        $(`#toc-wrapper #${activeId}`).ac('toc-item-active').siblings().rc('toc-item-active')
    }
    
    $(window).on('scroll', () => {
        tocToggle()
    })
    
    tocToggle()
    

    Tips

    锚点偏移

    本网站的header是fixed在顶部的,锚点不进行偏移会盖住标题。偏移方法:

    h1, h2, h3, h4, h5, h6{
        &:target{
            padding-top: 60px
        }
    }

    相关文章

      网友评论

        本文标题:cheerio制作markDown索引目录

        本文链接:https://www.haomeiwen.com/subject/baypkftx.html