js压缩代码后怎么生成source map_??markdown生成导航? #x27;[toc]#x27;足矣
背景
什么是toc? table of contents 是markdown中的導(dǎo)航信息,能夠通過heading和錨點(diǎn)快速定位。
最近在開發(fā)個人博客的時候,希望有一個生成目錄導(dǎo)航的功能,目的是做一個像語雀右上角一樣的導(dǎo)航欄:
使用的markdown渲染引擎是showdown,找了半天,只找到一個jquery寫的toc插件,也不支持nodejs。(很好,又是一個造輪子,開源,刷福報的好機(jī)會!)
于是就自己做了一個插件,支持兩大功能:
效果:
使用前:
使用后:
開發(fā)過程
汲取和熟悉
首先閱讀showdown的wiki,了解extension機(jī)制和寫法。了解到以下幾點(diǎn):
思路
老的思路:自己寫一個lang插件,在一開始引擎讀md的時候,就去收集信息,結(jié)果證明:?
原因: 實(shí)踐過程中,showdown有緩存機(jī)制,只會讀取一遍md內(nèi)容,之后讀的都是html的內(nèi)容,就無法收集toc的元信息了。
新思路:在output階段中解析html的h1到h6標(biāo)簽,收集heading信息,并替代[toc]的占位符,輸出到html中,結(jié)果證明:?
步驟以及代碼:
整個代碼的核心是這個正則:/(<h([1-6]).*?id="([^"]*?)".*?>(.+?)</h[1-6]>)|(<p>[toc]</p>)/g;
這個正則,獲取了h1-h6的標(biāo)題信息以及toc的占位符的位置和次數(shù)
第一步:
在這里,showdown-toc會去尋找并按出現(xiàn)次序收集tocItem和[toc]
// find and collect all headers and [toc] node;const collection: MetaInfo[] = [];source.replace(regex, (wholeMatch, _, level, anchor, text) => {if (wholeMatch === '<p>[toc]</p>') {collection.push({ type: 'toc' });} else {text = text.replace(/<[^>]+>/g, '');const tocItem = {anchor,level: Number(level),text,};// 如果傳了閉包的數(shù)組參數(shù)toc,就會把標(biāo)題信息推入if (toc) {toc.push(tocItem);}collection.push({type: 'header',...tocItem,});}return '';});tocItem長這樣:
type TocItem = {anchor: string; // 錨點(diǎn)level: number; // 標(biāo)題級別text: string; // 標(biāo)題內(nèi)容 };第二步
這里,出現(xiàn)[toc]之后,會收集這個[toc]到下個[toc]之間的標(biāo)題信息
// calculate toc infoconst tocCollection: TocItem[][] = [];collection.forEach(({ type }, index) => {if (type === 'toc') {if (collection[index + 1] && collection[index + 1].type === 'header') {const headers = [];const { level: levelToToc } = collection[index + 1] as TocItem;for (let i = index + 1; i < collection.length; i++) {if (collection[i].type === 'toc') break;const { level } = collection[i] as TocItem;if (level === levelToToc) {headers.push(collection[i] as TocItem);}}tocCollection.push(headers);} else {tocCollection.push([]);}}});第三步:
這個階段,會把source中的showdown給我們生成的<p>[toc]</p>標(biāo)簽替換成我們生成toc標(biāo)簽,也就是ol和li標(biāo)簽啦。然后把處理后的source返回給showdown就好了。整個插件也就完成了。
// replace [toc] node in sourcesource = source.replace(/<p>[toc]</p>[n]*/g, () => {const headers = tocCollection.shift();if (headers && headers.length) {const str = `<ol>${headers.map(({ text, anchor }) => `<li><a href="#${anchor}">${text}</a></li>`).join('')}</ol>n`;return str;}return '';});總結(jié)
整個插件很簡單,但是中間也遇到了不少坑,出現(xiàn)過思路的碰撞。實(shí)現(xiàn)的主要步驟邏輯如下:
歡迎pr
項目地址:https://github.com/ahungrynoob/showdown-toc
總結(jié)
以上是生活随笔為你收集整理的js压缩代码后怎么生成source map_??markdown生成导航? #x27;[toc]#x27;足矣的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python人工智能要学什么_为什么学人
- 下一篇: python中gui实现一个登录界面_P