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

- 点击索引单项跳转到相应标题
- 大号标题包含小号标题,小号标题向右缩进
- 滚动页面时自动切换索引项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索引目录的更多相关文章
- IntelliJ IDEA 转移C盘.IntelliJIdea(索引目录)
转移原因: C盘是机械硬盘,并且容量不多的情况下,建议转移. 转移步骤: 找到索引目录 win10系统下默认路径:C:\Users\asus\.IntelliJIdea2016.2 *复制或剪切到新的 ...
- lucene全文搜索之二:创建索引器(创建IKAnalyzer分词器和索引目录管理)基于lucene5.5.3
前言: lucene全文搜索之一中讲解了lucene开发搜索服务的基本结构,本章将会讲解如何创建索引器.管理索引目录和中文分词器的使用. 包括标准分词器,IKAnalyzer分词器以及两种索引目录的创 ...
- 【一天一道LeetCode】索引目录 ---C++实现
[一天一道LeetCode]汇总目录 这篇博客主要收藏了博主所做题目的索引目录,帮助各位读者更加快捷的跳转到对应题目 目录按照难易程度:easy,medium,hard来划分,读者可以按照难易程度进行 ...
- 使用word设置标题级别, 自动生成和大纲对应的多级列表, 自动生成索引目录
作为程序员,只会开发是不够的, 在日常工作中还需要掌握一些办公软件的的操作方法,word excel ppt精通不敢, 暂且入个门吧, 在前后台开发配合过程中,能写的一手好文档将会达到事半功倍的效果, ...
- IntelliJ IDEA 转移 C盘.IntelliJIdea 索引目录
IntelliJ IDEA 索引目录默认路径是 C:\Users\用户\.IntelliJIdea 转移步骤 1. 将 C:\Users\用户\.IntelliJIdea 索引目录剪切到要移动到的 ...
- lucene 多索引目录搜索实现方法
http://akululu.iteye.com/blog/314130 多索引目录就是要在多个索引目录的中进行比较搜索,类似概念在SQL中就是select * from TableA union s ...
- nginx索引目录配置
为了简单共享文件,有些人使用svn,有些人使用ftp,但是更多得人使用索引(index)功能.apache得索引功能强大,并且也是最常见得,nginx得auto_index实现得目录索引偏少,而且功能 ...
- Nginx中的root&alias文件路径及索引目录配置详解
这篇文章主要介绍了Nginx中的root&alias文件路径及索引目录配置,顺带讲解了root和alias命令的用法,需要的朋友可以参考下 root&alias文件路径配置ng ...
- 《Windows内核安全与驱动开发》阅读笔记 -- 索引目录
<Windows内核安全与驱动开发>阅读笔记 -- 索引目录 一.内核上机指导 二.内核编程环境及其特殊性 2.1 内核编程的环境 2.2 数据类型 2.3 重要的数据结构 2.4 函数调 ...
随机推荐
- java代码I/O流类
package com.aini; //流类rr //流操作的步骤: /*1.找到指定File 2.实例化字节流.InputStream/OutputStream/Reader/Writer 3.读/ ...
- 运行jar应用程序引用其他jar包的三种常用方法(jar命令)
参考:http://blog.csdn.net/wangmuming/article/details/44343017 方法一.使用Extension Classloader来加载 你可以把需要加载的 ...
- java中如何将OutputStream转换为InputStream
在不需要文件生成的情况下,直接将输出流转换成输入流.可使用下面的三种方法: 如果你曾经使用java IO编程,你会很快碰到这种情况,某个类在OutputStream上创建数据而你需要将它发送给某个需要 ...
- C# IL中间代码注入实现切面编程
背景及现状:之前分享的那篇“面向切面编程–渲染监控日志记录方案”中提供了利用RealProxy作为代理类来生成代理的面向切面的编程方法,那个方法可以实现面向切面编程进行日志记录,现在渲染主程序也是采用 ...
- 如何Catalog磁带库中的备份集
在NBU备份的环境中,可以使用以下步骤来Catalog磁带库中的备份集. 1. 查找需要Catalog的备份集名称 可以使用两种方法查找Oracle备份集. 方法一是使用RMAN的list命令查找,例 ...
- 使用百度地图API进行坐标系转换
最近在做移动APP的定位功能的时候发现系统GPS获取的位置信息再从百度地图API获取的实际地址总是有误差,偏离了好几个街道,但百度地图本身没这个问题.在网上查找一番发现了地图的坐标系一说,下面简单介绍 ...
- Java之——java.lang.NoSuchMethodException: [org.springframework.web.multipart.MultipartFile;.()
转自:https://blog.csdn.net/l1028386804/article/details/65449355 ava.lang.NoSuchMethodException: [org.s ...
- 数据库监听。数据库一次notify,Activity多次接收
今天项目中发现一个bug: (1)当uri数据库中有更新,会从数据库层DataService中通知应用层,调用notifyChange: mContext.getContentResolver().n ...
- C连接oracle数据库
int db_conn_main() { EXEC SQL BEGEIN DECLARE SECTION; +]; +]; +]; varchar username[]; varchar passwo ...
- [tensorflow]异或门的实现
一段小程序:待理解 import tensorflow as tf import numpy as np #输入训练数据,这里是python的list, 也可以定义为numpy的ndarray x_d ...