简介

             * 用Regex辅助生成文章目录 2.0
* 1、提高了功能的通用性(假定的文章格式更加普遍,即按照h2h3h4分级)
* 2、改善了代码的可读性(稍微牺牲了一点点性能,不过也无关紧要。。)
* 3、略微。。提高了扩展性(只需要重写generateDirectory方法就可以
* 生成自定义目录)
* 缺点:没有处理比较脏的情况,需要人工确保html干净

测试用例

输入:

        <h2>你好</h2>
<p>dasjdalsjdlsasjdlsczxcnzxczxczxc00</p>
<h3>dasda</h3>
<h4>23981023812090839dajldjasldjalsjd</h4>
<p>dasdasjdlasjdlasjdlassjdalsdjalsdj</p>
<h4>21023812038129dajldjasldjalsjd</h4>
<p>dasdassjdlasjdlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlasjddlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlasjdlasjdlasjdalsdjalsdj</p>
<h3>ddada</h3>
<p>dasdasjdlasjdlasjdlasjdalsdjalsdj</p>
<p>daasjdlasjdlasjdlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlasjdlasdlasjdalsdjalsdj</p>
<h2>hi</h2>
<h3>dadasdasda</h3>
<p>dasdasjdlasjdljdlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlasjdsjdlasjdalsdjalsdj</p>
<p>dasdasjjdlasjdlasjdlasjdalsdjalsdj</p>
<h3>dasasdassaddasda</h3>
<p>dasdasjdlasasjdlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlalasjdlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlasjdlasjdlasjdlasjdalsdjalsdj</p>
<h2>大家好</h2>
<p>asjdlasjdlaasjdlasjsdjalsdj</p>
<p>dsjdlasjdlasjdldlasjdalsdjalsdj</p>
<p>dasdasjdlasjdlasjdalsdjalsdj</p>

输出:

<div id="diy_right_menu">
<h2>索引</h2>
<ul>
<ol><li><a href="#anchor0">你好</a>
<ul><li><a href="#anchor1">dasda</a>
<ul><li><a href="#anchor2">23981023812090839dajldjasldjalsjd</a></li>
<li><a href="#anchor3">21023812038129dajldjasldjalsjd</a></li>
</ul>
</li>
<li><a href="#anchor4">ddada</a></li>
</ul>
</li>
<li><a href="#anchor5">hi</a>
<ul><li><a href="#anchor6">dadasdasda</a></li>
<li><a href="#anchor7">dasasdassaddasda</a></li>
</ul>
</li>
<li><a href="#anchor8">大家好</a></li>
</ol>
</ul>
</div>

<h2><a name="anchor0"></a>你好</h2>
<p>dasjdalsjdlsasjdlsczxcnzxczxczxc00</p>
<h3><a name="anchor1"></a>dasda</h3>
<h4><a name="anchor2"></a>23981023812090839dajldjasldjalsjd</h4>
<p>dasdasjdlasjdlasjdlassjdalsdjalsdj</p>
<h4><a name="anchor3"></a>21023812038129dajldjasldjalsjd</h4>
<p>dasdassjdlasjdlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlasjddlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlasjdlasjdlasjdalsdjalsdj</p>
<h3><a name="anchor4"></a>ddada</h3>
<p>dasdasjdlasjdlasjdlasjdalsdjalsdj</p>
<p>daasjdlasjdlasjdlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlasjdlasdlasjdalsdjalsdj</p>
<h2><a name="anchor5"></a>hi</h2>
<h3><a name="anchor6"></a>dadasdasda</h3>
<p>dasdasjdlasjdljdlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlasjdsjdlasjdalsdjalsdj</p>
<p>dasdasjjdlasjdlasjdlasjdalsdjalsdj</p>
<h3><a name="anchor7"></a>dasasdassaddasda</h3>
<p>dasdasjdlasasjdlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlalasjdlasjdlasjdalsdjalsdj</p>
<p>dasdasjdlasjdlasjdlasjdlasjdalsdjalsdj</p>
<h2><a name="anchor8"></a>大家好</h2>
<p>asjdlasjdlaasjdlasjsdjalsdj</p>
<p>dsjdlasjdlasjdldlasjdalsdjalsdj</p>
<p>dasdasjdlasjdlasjdalsdjalsdj</p>

代码

追加,偶尔会出现BUG,有序列表与无序列表有时候会乱用。仍需人工检查、修正。

<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
</head> <body>
<textarea id="big-textarea" placeholder="paste your origin html text here..." rows="30" cols="150">
</textarea>
<button id="big-button">Generate</button> <script type="text/javascript">
/**
* 用Regex辅助生成文章目录 2.0
* 1、提高了功能的通用性(假定的文章格式更加普遍,即按照h2h3h4分级)
* 2、改善了代码的可读性(稍微牺牲了一点点性能,不过也无关紧要。。。)
* 3、略微。。提高了扩展性(只需要重写generateDirectory方法就可以
* 生成自定义目录)
* 缺点:没有处理比较脏的情况,需要人工确保html干净
*/
let button = document.querySelector('#big-button');
button.addEventListener('click', event => {
let textArea = document.querySelector('#big-textarea');
let inputHtml = textArea.value;
textArea.value = addDirectoryTo(inputHtml);
});
</script> <script type="text/javascript">
/**
* 返回生成目录后的inputHtml
* @param {Object} inputHtml 原始html
*/
function addDirectoryTo(inputHtml) {
// 给h2 h3 h4加上锚点
let modifiedHtml = addAnchorTo(inputHtml);
// 提取h2 h3 h4标题
let titles = extractTitles(inputHtml);
// 利用h2 h3 h4标题生成目录
let directory = generateDirectory(titles);
// 将目录和修改后的html拼接后返回
return directory + modifiedHtml;
}
</script> <script type="text/javascript">
/**
* Title类属性↓
* text:string,存该标题中的文字
* level:Number,标题等级
* subTitles:list,用来存子标题
*/
function Title(h2h3h4) {
/**
* 构造器调用示例:new Title("<h2>二级标题</h2>")
*/
if (h2h3h4 != undefined) {
let extractedInfo = this.patternOfh2h3h4.exec(h2h3h4);
this.text = extractedInfo[2];
this.level = Number(extractedInfo[1]);
this.subTitles = [];
}
} Title.prototype.patternOfh2h3h4 = /<h([234])>([^]+?)<\/h[234]>/;
</script> <script type="text/javascript">
/**
* 返回给h2 h3 h4加上锚点后的html
* @param {Object} inputHtml 原始html
*/
function addAnchorTo(inputHtml) {
let patternOfh2h3h4 = /(<h[234]>)/g;
let indexOfAnchor = 0;
let modifyh2h3h4 = (_, h2h3h4) => {
return `${h2h3h4}<a name="anchor${indexOfAnchor++}"></a>`;
};
let modifiedHtml = inputHtml.replace(patternOfh2h3h4, modifyh2h3h4);
return modifiedHtml;
} /**
* 返回包含二级标题对象的list
* @param {Object} inputHtml 原始html
*/
function extractTitles(inputHtml) {
let titles = [];
let patternOfh2h3h4 = /<h[234]>[^]+?<\/h[234]>/g; // 非贪婪匹配
// 遍历正则匹配项
let match;
while (match = patternOfh2h3h4.exec(inputHtml)) {
let title = new Title(match[0]);
properPostion(titles, title.level).push(title);
}
return titles;
} const TOP_LEVEL = 2;
/**
* 返回某个标题的subTitles或者最终的titleList
* 给标题找合适的插入位置,为了不让extractTitles太长才抽象出来的。
* @param {Object} titles
* @param {Object} level 待插入标题的level
*/
function properPostion(titles, level) {
for (let i = TOP_LEVEL; i != level; ++i) {
titles = titles[titles.length - 1].subTitles;
}
return titles;
} /**
* 返回根据标题生成的目录,这个方法可以根据需要自定义
* @param {Object} titles 包含二级标题对象的list
*/
function generateDirectory(titles) {
return generateDiy_right_menu(titles);
} function generateDiy_right_menu(titles) {
let indexOfAnchor = 0;
let divBody = "";
let visitTitle = function(title, first=false) {
if (!first) {
divBody += `<li><a href="#anchor${indexOfAnchor++}">${title.text}</a>`;
}
if (title.subTitles.length != 0) {
if (!first) {
divBody += '\n<ul>';
} else {
divBody += '\n<ol>';
}
for (let i = 0; i != title.subTitles.length; ++i) {
visitTitle(title.subTitles[i]);
}
if (!first) {
divBody += '</ul>\n';
} else {
divBody += '</ol>\n';
}
}
if (!first) {
divBody += '</li>\n';
}
}
let root = new Title(); // 便于遍历titles
root.subTitles = titles;
visitTitle(root, true); let divHead = '<div id="diy_right_menu">\n<h2>索引</h2>\n<ul>\n';
let divTail = '</ul>\n</div>\n';
return divHead + divBody + divTail;
}
</script>
</body> </html>

JavaScript笔记 #08# 用Regex辅助生成文章目录 V2.0的更多相关文章

  1. JavaScript笔记 #05# 用Regex辅助生成文章目录

    PS. 用来生成个人笔记的目录 1.输入:html文本 <h2>Notes</h2> <p>1.小标题1.正文正文正文</p> <div clas ...

  2. CSDN中根据文章自动生成文章目录

    概述 CSDN中有根据文件内容中H标签在文章中自动生成文章目录,看起来比较专业,就想把它搬到自己的博客园中.类似下图 提取JS脚本 通过浏览器开发者工具(IE/Chrome)找到产生文章目录javas ...

  3. 使用autoc js生成文章目录(侧边)导航栏

    介绍: autocjs 是一个专门用来生成文章目录(Table of Contents)导航的工具.autocjs 会查找文章指定区域中的所有 h1~h6 的标签,并自动分析文章的层次结构,生成文章的 ...

  4. WPS生成文章目录

    WPS生成文章目录 1.引用–>插入目录...即可!

  5. 用React实现一个自动生成文章目录的组件

    原文地址:小寒的博客 功能介绍 这个组件的效果呐,就是你在浏览这个页面的时候点击右上角的叉叉看到的那个文章目录. 功能很简单,就是根据文章内容自动生成这个目录,可以快速跳转. 需要的知识点 正则 do ...

  6. javascript笔记08:javascript的if...else语句

    案例代码如下: <!DOCTYPE html> <html> <body> <p>点击这个按钮,获得基于时间的问候.</p> <but ...

  7. HelloDjango 第 11 篇:自动生成文章摘要

    作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 博客文章的模型有一个 excerpt 字段,这个字段用于存储文章的摘要.目前为止,还只 ...

  8. 使用office添加文章目录

    当我们用word录入完文章,文章里有段落,段落里又有小标题,每一种标题的格式不尽相同,word为我们提供了相当丰富的标题格式,如:正文,无间隔,标题1,标题2,标题3,标题4,副标题,强调,要点... ...

  9. CSDN添加文章目录

    在发表的文章中,系统根据文章中H1到H6标签自动生成文章目录. 一.发表文章的时候合理使用“标题”标签. 二.目录生成.只要在文章中使用了“标题1”这样的功能,就可以在博文开头看到文章的目录.

随机推荐

  1. java.lang.SecurityException: Permission Denial: writing android.support.v4.content.FileProvider uri

    在使用红米手机拍摄照片时,出现闪退的情况. 调用系统相机拍摄照片,使用FileProvider.getUriForFile传入Uri时,报异常 java.lang.SecurityException: ...

  2. Go vs Erlang - 转

    From http://zhang.hu/go-vs-erlang/ Go vs Erlang 因为 云巴 系统对高并发.低延迟的需求,我们对各个语言.平台做了很多的调研比较工作.这自然就包括致力于开 ...

  3. C# 指定http请求使用Tls1.2

    转载于 https://blog.csdn.net/yanghaitian/article/details/77498872 客户端语言 版本 类库 是否支持 兼容方案   Java 1.6.115之 ...

  4. MD5、SHA1加密java 16位32位

    MD5.SHA1加密java 16位32位 import java.math.BigInteger; import java.security.MessageDigest; public class ...

  5. opencv-resize()放缩函数简介

    主要介绍函数resize(); 图像缩放的效果图如下: 主程序代码及函数解释如下所示: /******************************************************* ...

  6. 如何解决“504 Gateway Time-out”错误

    做网站的同学经常会发现一些nginx服务器访问时候提示504 Gateway Time-out错误,一般情况下是由nginx默认的fastcgi进程响应慢引起的,但也有其他情况,这里我总结了一些解决办 ...

  7. mysql----------局域网数据库:如何让navicat链接局域网其他的数据库。

    1.找到被链接的数据库,打开以后有一个自带的mysql数据库,打开以后下面有一个user表,把里面的第一条数据的第一个字段改成% 百分号,然后保存,重启数据库,搞定 2.如果是linux下的话,记得把 ...

  8. 001-http协议-请求报文以及服务器响应状态

    Http协议的几个概念: 1.连接(Connection):浏览器和服务器之间传输数据的通道. 一般请求完毕就关闭,http不保持连接.不保持连接会降低处理速度(因为建立连接速度很慢),保持连接的话就 ...

  9. hive javaapi 002

    默认开启10000端口开启前,编辑hive-site.xml设置impersonation,防止hdfs权限问题,这样hive server会以提交用户的身份去执行语句,如果设置为false,则会以起 ...

  10. 5.JVM的内存区域划分

    一.JVM介绍 1. 什么是JVM? JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟 ...