unified如何處理markdown解析器詳解
unified是什么
unified
是用于文檔處理的生態(tài)系統,核心包提供了文檔處理的流程控制,具體功能由生態(tài)系統中各個插件提供。例如我們如果需要處理markdown,就需要使用markdown處理相關的插件。當然除了markdwon以外,還提供了處理HTML、JSX等的插件。其良好的擴展能力能讓我們很方便的在解析文檔過程中添加各種新功能。
如果我們遇到了需要處理markdown文檔、markdown轉HTML、HTML轉markdown等操作,那么可以嘗試使用unified來作為解析器。
unified生態(tài)簡介
上面說到unified除了用于解析markdown外,還有各種各樣的插件用于不同類型的文檔解析。
unified主要有以下四個生態(tài)系統:
每個生態(tài)系統下面都有用于處理各自文檔類型的插件,以remark
生態(tài)來說,如常用有以下插件:
- remark-parse - 用于將markdown字符串轉換為語法樹。通常來講處理markdown都會首先用到這個插件,后續(xù)的插件會根據業(yè)務場景增刪或替換語法樹內容。
- remark-stringify - 用于將markdown語法樹轉換為markdown字符串,是
remark-parse
的逆過程,經過處理后的語法樹可通過該插件恢復成為markdown輸出。 - remark-frontmatter - 用于處理markdown的‘元信息’,
frontmatter
是一種在文檔頭部用于備注元信息的格式,通常我們用于配置該markdown的基本屬性如標題、作者、標簽等,這個插件可以幫助我們提取這些信息并轉成結構化對象。
工作原理
unified
工作流程由三個階段組成:
| ............................... process ....................................... | | .......... 解析(parse) ... | ... 處理(run) ... | ... 序列化(stringify) ..........| +--------+ +----------+ Input ->- | Parser | ->- Syntax Tree ->- | Compiler | ->- Output +--------+ | +----------+ X | +--------------+ | Transformers | +--------------+
Parse
該階段用于將Markdown, HTML, 或其他格式文檔轉換為抽象語法樹(AST),基于語法樹可以讓程序更容易處理非結構化文檔。常用的語法樹有以下幾種
remark-parse
插件就是在該階段工作。
Transform
該階段用于根據業(yè)務場景處理AST,是整個流程的核心階段,生態(tài)中大部分插件及我們自定義的插件大都運行在這個階段。當然這個階段是可選的,沒有這個階段也能運行,但是沒有太大意義。remark-frontmatter
插件就是在這個階段工作。
還有一類稱為橋接(Bridge)的插件也是運行在這個階段,這類插件用于不同結構的AST相互轉換。例如我們需要將處理后的Markdown轉換為HTML,就需要將mdast
轉換為hast
,常見的幾種Bridge插件有:
- remark-rehype — Markdown 轉 HTML
- rehype-remark — HTML 轉 Markdown
- remark-retext — Markdown 轉 自然語言
- rehype-retext — HTML 轉 自然語言
Stringify
該階段用于將AST序列化為字符串輸出。 remark-stringify
插件就是在這個階段工作。
牛刀小試
環(huán)境搭建
安裝依賴
npm install unified remark-parse remark-stringify remark-frontmatter js-yaml
編寫運行代碼
// index.js const unified = require('unified') console.log(unified)
運行
node index.js
報錯
處理ESM類型包
由于unified
使用的是ESM
方式打包,而我們通常寫的node代碼用CommonJS
方式在這里是無法正常運行的,所以我們需要使用ESM
的方式來編寫運行代碼。
- 首先將
index.js
改名為index.mjs
(使用package.json配置也行,這里不舉例了) - 將引入方式改為
ESM
的import
// index.mjs // 由于unified沒有導出default,這里要用{}括起來 import { unified } from 'unified' console.log(unified)
- 運行
node index.mjs
可以看到已經可以正常運行,基本運行環(huán)境就完成了。
最簡用法
修改運行文件
import { unified } from 'unified' import remarkParse from 'remark-parse' import remarkStringify from 'remark-stringify' // 初始化一個unified解析器 const res = unified() // 使用Markdown解析器將文本轉為AST .use(remarkParse) // 將MarkdownAST轉為字符串 .use(remarkStringify) // 開始同步執(zhí)行解析 .processSync('# hello unified') console.log(res)
這個例子僅是最基礎的運行沒有什么實際功能,運行結果:
加載文檔meta
import { unified } from 'unified' import remarkParse from 'remark-parse' import remarkFrontmatter from 'remark-frontmatter' import remarkStringify from 'remark-stringify' import yaml from 'js-yaml' const res = unified() .use(remarkParse) // 添加解析yaml的插件,會將具有yaml塊標志(默認為---)的文檔塊解析成為yaml類型節(jié)點, .use(remarkFrontmatter, ['yaml']) // 添加一個自定義插件來處理yaml類型節(jié)點 .use(() => (tree, vFile) => { console.log(tree) // unist-util-visit 提供了更多便捷訪問AST的工具,這里我們先簡單獲取 const node = tree.children.find(n => n.type == 'yaml') if(node) { // 使用yaml解析器解析yaml格式字符串 const meta = yaml.load(node.value) // { title: 'I AM TITLE', tags: [ 'unified', 'good' ] } console.log(meta) // 賦值到該文件的解析數據中返回給外部使用 vFile.data.meta = meta } }) .use(remarkStringify) .processSync(`--- title: I AM TITLE tags: - unified - good --- # hello unified' `) console.log(res)
從打印結果可以看到,經過remark-frontmatter
處理后,被---
標志包含的文檔塊被轉換成了yaml
類型的節(jié)點,我們就可以方便的基于這個節(jié)點來解析數據了。
同時我們還自定義了一個簡易的插件,用于處理yaml
類型的節(jié)點,最終結果如下所示,已經正確提取出出來Markdown中的自定義屬性數據:
一個實際使用例子:
dumi - 為組件研發(fā)而生的靜態(tài)站點框架
該項目使用了unified來將markdown轉換為react-jsx,markdown用于寫組件說明文檔,jsx用于渲染為網站。其中除了使用unified生態(tài)的部分插件外,dumi還實現了許多自定義的功能插件用于擴展markdown的語法。
本章后續(xù)將逐一拆解相關代碼,深入學習unified插件開發(fā)及實戰(zhàn)運用,更多關于unified處理markdown解析器的資料請關注腳本之家其它相關文章!
以上就是unified如何處理markdown解析器詳解的詳細內容,更多關于unified處理markdown解析器的資料請關注腳本之家其它相關文章!
相關文章
TypeScript編寫自動創(chuàng)建長度固定數組的類型工具詳解
這篇文章主要為大家介紹了TS編寫自動創(chuàng)建長度固定數組的類型工具詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08業(yè)務層hooks封裝useSessionStorage實例詳解
這篇文章主要為大家介紹了業(yè)務層hooks封裝useSessionStorage實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08Javascript中彈窗confirm與prompt的區(qū)別
今天小編就為大家分享一篇關于Javascript中彈窗confirm與prompt的區(qū)別,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-10-10