易于使用的 Markdown 編輯器,為適配不同的應用場景而生
English | Demo
? 簡介
Vditor 是一款瀏覽器端的 Markdown 編輯器,支持所見即所得、即時渲染(類似 Typora)和分屏預覽模式。它使用 TypeScript 實現,支持原生 JavaScript、Vue、React、Angular,提供桌面版。
歡迎到 Vditor 官方討論區了解更多。同時也歡迎關注 B3log 開源社區微信公眾號 B3log開源
:
?️ 背景
隨著 Markdown 排版方式的普及,越來越多的應用開始集成 Markdown 編輯器。目前主流可集成的 Markdown 編輯器現狀如下:
- 有的僅支持分屏預覽,即編輯區和預覽區分離
- 有的同時支持所見即所得和分屏預覽,但所見即所得模式下不能完整支持 Markdown 語法排版
- 幾乎沒有類似 Typora 的即時渲染
而這三點恰好對應了三種應用場景:
- 分屏預覽:適配傳統的 Markdown 使用場景,適合大屏下編輯排版
- 所見即所得:對不熟悉 Markdown 的用戶友好,熟悉 Markdown 的用戶也可以無縫使用
- 即時渲染:理論上這是最為優雅的 Markdown 編輯方式,讓熟悉 Markdown 的用戶能夠更專注于內容創作
所以,一個能夠適配應用場景的 Markdown 編輯器至關重要,它需要考慮到:
- 傳統 Markdown 用戶的使用場景,提供分屏預覽
- 富文本編輯用戶的使用場景,提供所見即所得
- 高階 Markdown 用戶的使用場景,提供即時渲染
Vditor 在這些方面做了努力,希望能為現代化的通用 Markdown 編輯領域做出一些貢獻。
✨ 特性
- 支持三種編輯模式:所見即所得(wysiwyg)、即時渲染(ir)、分屏預覽(sv)
- 支持大綱、數學公式、腦圖、圖表、流程圖、甘特圖、時序圖、五線譜、多媒體、語音閱讀、標題錨點、代碼高亮及復制、graphviz 渲染
- 內置安全過濾、導出、圖片懶加載、任務列表、多平臺預覽、多主題切換、復制到微信公眾號/知乎功能
- 實現 CommonMark 和 GFM 規范,可對 Markdown 進行格式化和語法樹查看,并支持 10+ 項配置
- 工具欄包含 36+ 項操作,除支持擴展外還可對每一項中的快捷鍵、提示、提示位置、圖標、點擊事件、類名、子工具欄進行自定義
- 表情/at/話題等自動補全擴展
- 可使用拖拽、剪切板粘貼上傳,顯示實時上傳進度,支持 CORS 跨域上傳
- 實時保存內容,防止意外丟失
- 錄音支持,用戶可直接發布語音
- 粘貼 HTML 自動轉換為 Markdown,如粘貼中包含外鏈圖片可通過指定接口上傳到服務器
- 支持主窗口大小拖拽、字符計數
- 多主題支持,內置黑白綠三套主題
- 多語言支持,內置中、英、韓文本地化
- 支持主流瀏覽器,對移動端友好
? 編輯模式
所見即所得(WYSIWYG)
所見即所得模式對不熟悉 Markdown 的用戶較為友好,熟悉 Markdown 的話也可以無縫使用。
即時渲染(IR)
即時渲染模式對熟悉 Typora 的用戶應該不會感到陌生,理論上這是最優雅的 Markdown 編輯方式。
分屏預覽(SV)
傳統的分屏預覽模式適合大屏下的 Markdown 編輯。
? 語法支持
- 所有 CommonMark 語法:分隔線、ATX 標題、Setext 標題、縮進代碼塊、圍欄代碼塊、HTML 塊、鏈接引用定義、段落、塊引用、列表、反斜杠轉義、HTML 實體、行級代碼、強調、加粗、鏈接、圖片、行級 HTML、硬換行、軟換行和純文本。
- 所有 GFM 語法:表格、任務列表項、刪除線、自動鏈接、XSS 過濾
- 常用 Markdown 擴展語法:腳注、ToC、自定義標題 ID
- 圖表語法
- 流程圖、時序圖、甘特圖,通過 Mermaid 支持
- Graphviz
- 折線圖、餅圖、腦圖等,通過 ECharts 支持
- 五線譜:通過 abc.js 支持
- 數學公式:數學公式塊、行級數學公式,通過 MathJax 和 KaTeX 支持
- YAML Front Matter
- 中文語境優化
- 中西文之間插入空格
- 術語拼寫修正
- 中文后跟英文逗號句號等標點替換為中文對應標點
以上大部分特性可以通過開關配置是否啟用,開發者可根據自己的應用場景選擇搭配。
? 案例
- Sym 一款用 Java 實現的現代化社區(論壇/BBS/社交網路/部落格)平臺
- Solo & Pipe B3log 分布式社區的部落格端節點,歡迎加入下一代社區網路
- 思源筆記 一款 Markdown 塊級引用和雙向鏈接的網狀筆記應用
- Arya 基于 Vue、Vditor,所構建的在線 Markdown 編輯器
- 更多案例
?️ 使用文檔
CommonJS
- 安裝依賴
npm install vditor --save
- 在代碼中引入并初始化對象,可參考 index.js
import Vditor from 'vditor'
import "~vditor/src/assets/scss/index"
const vditor = new Vditor(id, {options...})
HTML script
- 在 HTML 中插入 CSS 和 JavaScript,可參考 demo
<!-- ⚠️生產環境請指定版本號,如 https://cdn.jsdelivr.net/npm/[email protected]/dist... -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vditor/dist/index.css" />
<script src="https://cdn.jsdelivr.net/npm/vditor/dist/index.min.js" defer></script>
示例代碼
- 官方示例 / 示例源碼
- CommonJS Editor
- CommonJS Render
主題
編輯器主題
編輯器所展現的外觀。內置 classic,dark 2 套主題。
- 編輯器初始化時可通過
options.theme
設置內置主題 - 初始化完成后可通過
setTheme
更新編輯器主題 - 可通過修改 index.scss 中的變量對主題顏色進行定制
- 可參考現有結構和類名在原有基礎上進行修改
內容主題
Markdown 輸出的 HTML 所展現的外觀。內置 light,dark,wechat 3 套主題。支持內容主題擴展接口。
- 需在顯示元素上添加
class="vditor-reset"
- 編輯器初始化時可通過
options.preview.theme
設置內置或自己開發的主題列表 - 內容渲染初始化時可通過
IPreviewOptions.theme
設置內置或自己開發的主題 - 初始化完成后可通過
setTheme
或setContentTheme
更新內容主題
代碼主題
代碼塊所展現的外觀。內置 GitHub 等 36 套主題。
- 編輯器初始化時可通過
options.preview.hljs
對代碼塊樣式、行號、是否啟用進行設置 - 內容渲染初始化時可通過
IPreviewOptions.hljs
對代碼塊樣式、行號、是否啟用進行設置 - 初始化完成后可通過
setTheme
或setCodeTheme
更新代碼主題
API
id
可填入元素 id
或元素自身 HTMLElement
⚠️:當填入元素自身的 HTMLElement
時需設置 options.cache.id
或將 options.cache.enable
設置為 false
options
說明 | 默認值 | |
---|---|---|
after | 編輯器異步渲染完成后的回調方法 | – |
height | 編輯器總高度 | ‘auto’ |
minHeight | 編輯區域最小高度 | – |
width | 編輯器總寬度,支持 % | ‘auto’ |
placeholder | 輸入區域為空時的提示 | ” |
lang | 多語言:en_US, ja_JP, ko_KR, zh_CN | ‘zh_CN’ |
input(value: string, previewElement?: HTMLElement) | 輸入后觸發 | – |
focus(value: string) | 聚焦后觸發 | – |
blur(value: string) | 失焦后觸發 | – |
esc(value: string) | esc 按下后觸發 | – |
ctrlEnter(value: string) | ⌘/ctrl+enter 按下后觸發 | – |
select(value: string) | 編輯器中選中文字后觸發 | – |
tab | tab 鍵操作字符串,支持 \t 及任意字符串 |
– |
typewriterMode | 是否啟用打字機模式 | false |
cdn | 配置自建 CDN 地址 | https://cdn.jsdelivr.net/npm/vditor@${VDITOR_VERSION} |
mode | 可選模式:sv, ir, wysiwyg | ‘ir’ |
debugger | 是否顯示日志 | false |
value | 編輯器初始化值 | ” |
theme | 主題:classic, dark | ‘classic’ |
icon | 圖標風格:ant, material | ‘ant’ |
outline | 是否展現大綱 | false |
options.toolbar
- 工具欄,可使用 name 進行簡寫:
toolbar: ['emoji', 'br', 'bold', '|', 'line']
。默認值參見 src/ts/util/Options.ts - name 可枚舉為:
emoji
,headings
,bold
,italic
,strike
,|
,line
,quote
,list
,ordered-list
,check
,outdent
,indent
,code
,inline-code
,insert-after
,insert-before
,undo
,redo
,upload
,link
,table
,record
,edit-mode
,both
,preview
,fullscreen
,outline
,code-theme
,content-theme
,export
,devtools
,info
,help
,br
- 當
name
不在枚舉中時,可以添加自定義按鈕,格式如下:
new Vditor('vditor', {
toolbar: [
{
hotkey: '⌘-⇧-S',
name: 'sponsor',
tipPosition: 's',
tip: '成為贊助者',
className: 'right',
icon: '<svg t="1589994565028" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2808" width="32" height="32"><path d="M506.6 423.6m-29.8 0a29.8 29.8 0 1 0 59.6 0 29.8 29.8 0 1 0-59.6 0Z" fill="#0F0F0F" p-id="2809"></path><path d="M717.8 114.5c-83.5 0-158.4 65.4-211.2 122-52.7-56.6-127.7-122-211.2-122-159.5 0-273.9 129.3-273.9 288.9C21.5 562.9 429.3 913 506.6 913s485.1-350.1 485.1-509.7c0.1-159.5-114.4-288.8-273.9-288.8z" fill="#FAFCFB" p-id="2810"></path><path d="M506.6 926c-22 0-61-20.1-116-59.6-51.5-37-109.9-86.4-164.6-139-65.4-63-217.5-220.6-217.5-324 0-81.4 28.6-157.1 80.6-213.1 53.2-57.2 126.4-88.8 206.3-88.8 40 0 81.8 14.1 124.2 41.9 28.1 18.4 56.6 42.8 86.9 74.2 30.3-31.5 58.9-55.8 86.9-74.2 42.5-27.8 84.3-41.9 124.2-41.9 79.9 0 153.2 31.5 206.3 88.8 52 56 80.6 131.7 80.6 213.1 0 103.4-152.1 261-217.5 324-54.6 52.6-113.1 102-164.6 139-54.8 39.5-93.8 59.6-115.8 59.6zM295.4 127.5c-72.6 0-139.1 28.6-187.3 80.4-47.5 51.2-73.7 120.6-73.7 195.4 0 64.8 78.3 178.9 209.6 305.3 53.8 51.8 111.2 100.3 161.7 136.6 56.1 40.4 88.9 54.8 100.9 54.8s44.7-14.4 100.9-54.8c50.5-36.3 108-84.9 161.7-136.6 131.2-126.4 209.6-240.5 209.6-305.3 0-74.9-26.2-144.2-73.7-195.4-48.2-51.9-114.7-80.4-187.3-80.4-61.8 0-127.8 38.5-201.7 117.9-2.5 2.6-5.9 4.1-9.5 4.1s-7.1-1.5-9.5-4.1C423.2 166 357.2 127.5 295.4 127.5z" fill="#141414" p-id="2811"></path><path d="M353.9 415.6m-33.8 0a33.8 33.8 0 1 0 67.6 0 33.8 33.8 0 1 0-67.6 0Z" fill="#0F0F0F" p-id="2812"></path><path d="M659.3 415.6m-33.8 0a33.8 33.8 0 1 0 67.6 0 33.8 33.8 0 1 0-67.6 0Z" fill="#0F0F0F" p-id="2813"></path><path d="M411.6 538.5c0 52.3 42.8 95 95 95 52.3 0 95-42.8 95-95v-31.7h-190v31.7z" fill="#5B5143" p-id="2814"></path><path d="M506.6 646.5c-59.6 0-108-48.5-108-108v-31.7c0-7.2 5.8-13 13-13h190.1c7.2 0 13 5.8 13 13v31.7c0 59.5-48.5 108-108.1 108z m-82-126.7v18.7c0 45.2 36.8 82 82 82s82-36.8 82-82v-18.7h-164z" fill="#141414" p-id="2815"></path><path d="M450.4 578.9a54.7 27.5 0 1 0 109.4 0 54.7 27.5 0 1 0-109.4 0Z" fill="#EA64F9" p-id="2816"></path><path d="M256 502.7a32.1 27.5 0 1 0 64.2 0 32.1 27.5 0 1 0-64.2 0Z" fill="#EFAFF9" p-id="2817"></path><path d="M703.3 502.7a32.1 27.5 0 1 0 64.2 0 32.1 27.5 0 1 0-64.2 0Z" fill="#EFAFF9" p-id="2818"></path></svg>',
click () {alert('捐贈地址:https://ld246.com/sponsor')},
}],
})
說明 | 默認值 | |
---|---|---|
name | 唯一標示 | – |
icon | svg 圖標 | – |
tip | 提示 | – |
tipPosition | 提示位置:ne, nw | – |
hotkey | 快捷鍵,格式為⌘/ctrl-key 或 ⌘/ctrl-⇧/shift-key | – |
suffix | 插入編輯器中的后綴 | – |
prefix | 插入編輯器中的前綴 | – |
click() | 自定義按鈕點擊時觸發的事件 | – |
className | 樣式名 | ” |
toolbar?: Array<options.toolbar> | 子菜單 | – |
options.toolbarConfig
說明 | 默認值 | |
---|---|---|
hide | 是否隱藏工具欄 | false |
pin | 是否固定工具欄 | false |
options.counter
說明 | 默認值 | |
---|---|---|
enable | 是否啟用計數器 | false |
max | 允許輸入的最大值 | – |
type | 統計類型:md,text | ‘md’ |
options.cache
說明 | 默認值 | |
---|---|---|
enable | 是否使用 localStorage 進行緩存 | true |
id | 緩存 key,第一個參數為元素且啟用緩存時必填 | – |
after(html: string): string | 緩存后的回調 | – |
options.comment
⚠️:僅支持 wysiwyg 模式
說明 | 默認值 | |
---|---|---|
enable | 是否啟用評論模式 | false |
add(id: string, text: string, commentsData: ICommentsData[]) | 添加評論回調 | – |
remove(ids: string[]) | 刪除評論回調 | – |
scroll(top: number) | 滾動回調 | – |
adjustTop(commentsData: ICommentsData[]) | 文檔修改時,適配評論高度 | – |
options.preview
說明 | 默認值 | |
---|---|---|
delay | 預覽 debounce 毫秒間隔 | 1000 |
maxWidth | 預覽區域最大寬度 | 800 |
mode | 顯示模式:both, editor | ‘both’ |
url | md 解析請求 | – |
parse(element: HTMLElement) | 預覽回調 | – |
transform(html: string): string | 渲染之前回調 | – |
options.preview.hljs
說明 | 默認值 | |
---|---|---|
enable | 是否啟用代碼高亮 | true |
style | 可選值參見 Chroma | github |
lineNumber | 是否啟用行號 | false |
options.preview.markdown
說明 | 默認值 | |
---|---|---|
autoSpace | 自動空格 | false |
fixTermTypo | 自動矯正術語 | false |
chinesePunct | 自動矯正標點 | false |
toc | 插入目錄 | false |
footnotes | 腳注 | true |
codeBlockPreview | wysiwyg 和 ir 模式下是否對代碼塊進行渲染 | true |
mathBlockPreview | wysiwyg 和 ir 模式下是否對數學公式進行渲染 | true |
paragraphBeginningSpace | 段落開頭空兩個 | false |
sanitize | 是否啟用過濾 XSS | true |
listStyle | 為列表添加 data-style 屬性 | false |
linkBase | 鏈接相對路徑前綴 | ” |
linkPrefix | 鏈接強制前綴 | ” |
mark | 啟用 mark 標記 | false |
options.preview.theme
說明 | 默認值 | |
---|---|---|
current | 當前主題 | “light” |
list | 可選主題列表 | { dark: “Dark”, light: “Light”, wechat: “WeChat” } |
path | 主題樣式地址 | https://cdn.jsdelivr.net/npm/vditor@${VDITOR_VERSION}/dist/css/content-theme |
options.preview.math
說明 | 默認值 | |
---|---|---|
inlineDigit | 內聯數學公式起始 $ 后是否允許數字 | false |
macros | 使用 MathJax 渲染時傳入的宏定義 | {} |
engine | 數學公式渲染引擎:KaTeX, MathJax | ‘KaTeX’ |
options.preview.actions?: Array<IPreviewAction | IPreviewActionCustom>
默認值為 [“desktop”, “tablet”, “mobile”, “mp-wechat”, “zhihu”]。
可從默認值中挑選進行配置,也可使用以下字段進行自定制開發。
說明 | 默認值 | |
---|---|---|
key | 按鈕唯一標識,不能為空 | – |
text | 按鈕文字 | – |
tooltip | 提示 | – |
className | 按鈕類名 | – |
click(key: string) | 按鈕點擊回調事件 | – |
options.hint
說明 | 默認值 | |
---|---|---|
delay | 提示 debounce 毫秒間隔 | 200 |
emoji | 默認表情,可從 lute/emoji_map 中選取,也可自定義 | { ‘+1’: ‘?’, ‘-1’: ‘?’, ‘heart’: ‘❤️’, ‘cold_sweat’: ‘?’ } |
emojiTail | 常用表情提示 | – |
emojiPath | 表情圖片地址 | https://cdn.jsdelivr.net/npm/vditor@${VDITOR_VERSION}/dist/images/emoji |
extend: IHintExtend[] | 對 @/話題等關鍵字自動補全的擴展 | [] |
interface IHintExtend {
key: string;
hint?(value: string): Array<{
html: string;
value: string;
}>;
}
options.upload
- 文件上傳的數據結構如下。后端返回的數據結構不一致時,可使用
format
進行轉換。
// POST data
xhr.send(formData); // formData = FormData.append("file[]", File)
// return data
{
"msg": "",
"code": 0,
"data": {
"errFiles": ['filename', 'filename2'],
"succMap": {
"filename3": "filepath3",
"filename3": "filepath3"
}
}
}
- 為了防止站外圖片失效,
linkToImgUrl
可將剪貼板中的站外圖片地址傳到服務器端進行保存處理,其數據結構如下:
// POST data
xhr.send(JSON.stringify({url: src})); // src 為站外圖片地址
// return data
{
msg: '',
code: 0,
data : {
originalURL: '',
url: ''
}
}
success
,format
,error
不會同時觸發,具體調用情況如下:
if (xhr.status === 200) {
if (vditor.options.upload.success) {
vditor.options.upload.success(editorElement, xhr.responseText);
} else {
let responseText = xhr.responseText;
if (vditor.options.upload.format) {
responseText = vditor.options.upload.format(files as File [], xhr.responseText);
}
genUploadedLabel(responseText, vditor);
}
} else {
if (vditor.options.upload.error) {
vditor.options.upload.error(xhr.responseText);
} else {
vditor.tip.show(xhr.responseText);
}
}
說明 | 默認值 | |
---|---|---|
url | 上傳 url | ” |
max | 上傳文件最大 Byte | 10 * 1024 * 1024 |
linkToImgUrl | 剪切板中包含圖片地址時,使用此 url 重新上傳 | ” |
linkToImgCallback(responseText: string) | 圖片地址上傳回調 | – |
linkToImgFormat(responseText: string): string | 對圖片地址上傳的返回值進行格式化 | – |
success(editor: HTMLPreElement, msg: string) | 上傳成功回調 | – |
error(msg: string) | 上傳失敗回調 | – |
token | CORS 上傳驗證,頭為 X-Upload-Token | – |
withCredentials | 跨站點訪問控制 | false |
headers | 請求頭設置 | – |
filename(name: string): string | 文件名安全處理 | name => name.replace(/\W/g, ”) |
accept | 文件上傳類型,同 input accept | – |
validate(files: File[]) => string | boolean | 校驗,成功時返回 true 否則返回錯誤資訊 | – |
handler(files: File[]) => string | null | 自定義上傳,當發生錯誤時返回錯誤資訊 | – |
format(files: File[], responseText: string): string | 對服務端返回的數據進行轉換,以滿足內置的數據結構 | – |
file(files: File[]): File[] | 將上傳的文件處理后再返回 | – |
setHeaders(): { [key: string]: string } | 上傳前使用返回值設置頭 | – |
extraData: { [key: string]: string | Blob } | 為 FormData 添加額外的參數 | – |
multiple | 上傳文件是否為多個 | true |
fieldName | 上傳字段名稱 | ‘file[]’ |
options.resize
說明 | 默認值 | |
---|---|---|
enable | 是否支持大小拖拽 | false |
position | 拖拽欄位置:top, bottom | ‘bottom’ |
after(height: number) | 拖拽結束的回調 | – |
options.classes
說明 | 默認值 | |
---|---|---|
preview | 預覽元素上的 className | ” |
methods
說明 | |
---|---|
getValue() | 獲取 Markdown 內容 |
getHTML() | 獲取 HTML 內容 |
insertValue(value: string, render = true) | 在焦點處插入內容,并默認進行 Markdown 渲染 |
focus() | 聚焦到編輯器 |
blur() | 讓編輯器失焦 |
disabled() | 禁用編輯器 |
enable() | 解除編輯器禁用 |
getSelection(): string | 返回選中的字符串 |
setValue(markdown: string, clearStack = false) | 設置編輯器內容且選中清空歷史棧 |
clearStack() | 清空撤銷和重做記錄棧 |
renderPreview(value?: string) | 設置預覽區域內容 |
getCursorPosition():{top: number, left: number} | 獲取焦點位置 |
deleteValue() | 刪除選中內容 |
updateValue(value: string) | 更新選中內容 |
isUploading() | 上傳是否還在進行中 |
clearCache() | 清除緩存 |
disabledCache() | 禁用緩存 |
enableCache() | 啟用緩存 |
html2md(value: string) | HTML 轉 md |
tip(text: string, time: number) | 消息提示。time 為 0 將一直顯示 |
setPreviewMode(mode: “both” | “editor”) | 設置預覽模式 |
setTheme(theme: “dark” | “classic”, contentTheme?: string, codeTheme?: string, contentThemePath?: string) | 設置主題、內容主題及代碼塊風格 |
getCurrentMode(): string | 獲取編輯器當前編輯模式 |
destroy() | 銷毀編輯器 |
getCommentIds(): {id: string, top: number}[] | 獲取所有評論 |
hlCommentIds(ids: string[]) | 高亮評論 |
unHlCommentIds(ids: string[]) | 取消評論高亮 |
removeCommentIds(removeIds: string[]) | 刪除評論 |
static methods
- 不需要進行編輯操作時,僅需引入
method.min.js
后如下直接調用
Vditor.mermaidRender(document)
import VditorPreview from 'vditor/dist/method.min'
VditorPreview.mermaidRender(document)
- 需要對頁面中的 Markdown 進行渲染時可直接調用
preview
方法,參數如下:
previewElement: HTMLDivElement, // 使用該元素進行渲染
markdown: string, // 需要渲染的 markdown 原文
options?: IPreviewOptions {
anchor?: number; // 為標題添加錨點 0:不渲染;1:渲染于標題前;2:渲染于標題后,默認 0
customEmoji?: { [key: string]: string }; // 自定義 emoji,默認為 {}
lang?: (keyof II18nLang); // 語言,默認為 'zh_CN'
emojiPath?: string; // 表情圖片路徑
hljs?: IHljs; // 參見 options.preview.hljs
speech?: { // 對選中后的內容進行閱讀
enable?: boolean,
};
math?: IMath; // 數學公式渲染配置
cdn?: string; // 自建 CDN 地址
transform?(html: string): string; // 在渲染前進行的回調方法
after?(); // 渲染完成后的回調
lazyLoadImage?: string; // 設置為 Loading 圖片地址后將啟用圖片的懶加載
markdown?: options.preview.markdown;
theme?: options.preview.theme;
renderers?: ILuteRender; // 自定義渲染 https://ld246.com/article/1588412297062
}
- ⚠️
method.min.js
和index.min.js
不可同時引入
說明 | |
---|---|
mermaidRender(element: HTMLElement, cdn = options.cdn, theme = options.theme) | 流程圖/時序圖/甘特圖 |
flowchartRender(element: HTMLElement, cdn = options.cdn) | flowchart 渲染 |
codeRender(element: HTMLElement, lang: (keyof II18nLang) = “zh_CN”) | 為 element 中的代碼塊添加復制按鈕 |
chartRender(element: (HTMLElement | Document) = document, cdn = options.cdn, theme = options.theme) | 圖表渲染 |
mindmapRender(element: (HTMLElement | Document) = document, cdn = options.cdn, theme = options.theme) | 腦圖渲染 |
abcRender(element: (HTMLElement | Document) = document, cdn = options.cdn) | 五線譜渲染 |
md2html(mdText: string, options?: IPreviewOptions): Promise<string> | Markdown 文本轉換為 HTML,該方法需使用異步編程 |
preview(previewElement: HTMLDivElement, markdown: string, options?: IPreviewOptions) | 頁面 Markdown 文章渲染 |
highlightRender(hljsOption?: IHljs, element?: HTMLElement | Document, cdn = options.cdn) | 為 element 中的代碼塊進行高亮渲染 |
mediaRender(element: HTMLElement) | 為特定鏈接分別渲染為視訊、音頻、嵌入的 iframe |
mathRender(element: HTMLElement, options?: {cdn?: string, math?: IMath}) | 對數學公式進行渲染 |
speechRender(element: HTMLElement, lang?: (keyof II18nLang)) | 對選中的文字進行閱讀 |
graphvizRender(element: HTMLElement, cdn?: string) | 對 graphviz 進行渲染 |
outlineRender(contentElement: HTMLElement, targetElement: Element) | 對大綱進行渲染 |
lazyLoadImageRender(element: (HTMLElement | Document) = document) | 對啟用懶加載的圖片進行渲染 |
setCodeTheme(codeTheme: string, cdn = options.cdn) | 設置代碼主題,codeTheme 參見 options.preview.hljs.style |
setContentTheme(contentTheme: string, path: string) | 設置內容主題,contentTheme 參見 options.preview.theme.list |
? 開發文檔
原理相關
- 關于所見即所得 Markdown 編輯器的討論
- Vditor 實現 Markdown 所見即所得
- Lute 一款對中文語境優化的 Markdown 引擎,支持 Go 和 JavaScript
環境
- 安裝 node LTS 版本
- 下載最新代碼并解壓
- 根目錄運行
npm install
npm run start
啟動本地服務器,打開 http://localhost:9000- 修改代碼
npm run build
打包代碼到 dist 目錄
CDN 切換
由于使用了按需加載的機制,默認 CDN 為 https://cdn.jsdelivr.net/npm/vditor@版本號
如果代碼有修改或需要使用自建 CDN 的話,可按以下步驟進行操作:
- 初始化時,需對
options
及IPreviewOptions
中的cdn
,emojiPath
,themes
進行配置 highlightRender
,mathRender
,abcRender
,chartRender
,mermaidRender
,flowchartRender
,mindmapRender
,graphvizRender
,setCodeTheme
,setContentTheme
方法中需添加 cdn 參數- 將 build 成功的 dist 目錄或 jsDelivr 中的 dist 目錄拷貝至正確的位置
升級
版本升級時請仔細閱讀 CHANGELOG 中的升級部分
Ⓜ️ Markdown 使用指南
- 基礎語法
- 擴展語法
- 速查手冊
?️ 社區
- 官網
- 討論區
- 報告問題
? 授權
Vditor 使用 MIT 開源協議。
? 鳴謝
- Lute:? 一款結構化的 Markdown 引擎,支持 Go 和 JavaScript
- highlight.js:JavaScript syntax highlighter
- mermaid:Generation of diagram and flowchart from text in a similar manner as Markdown
- incubator-echarts:A powerful, interactive charting and visualization library for browser
- abcjs:JavaScript library for rendering standard music notation in a browser
?️ 歷史
我們在開發 Sym 的初期是直接使用 WYSIWYG 富文本編輯器的。那時候基于 HTML 的編輯器非常流行,項目中引用起來也很方便,也符合用戶當時的使用習慣。
后來,Markdown 的崛起逐步改變了大家的排版方式。再加上我們其他幾個項目都是面向程式員用戶的,所以遷移到 md 上也是大勢所趨。我們選擇了 CodeMirror,這是一款優秀的編輯器,它對開發者提供了豐富的編程接口,對各種瀏覽器的兼容性也比較好。
再后來,隨著我們項目業務需求方面的沉淀,使用 CodeMirror 有時候會感到比較“笨重”。比如要實現 @自動完成用戶名列表、插入 Emoji、上傳文件等就需要比較深入的二次開發,而這些業務需求恰恰是很多項目場景共有且必備的。
終于,我們決定開始在 Sym 中自己實現編輯器。隨著幾個版本的迭代,Sym 的編輯器也日趨成熟。在我們運營的社區YouMeLive上陸續有人問我們是否能將編輯器單獨抽離出來提供給大家使用。與此同時,我們的前端主程 V 同學對于維護分散在各個項目中的編輯器也感到有點力不從心,外加對 TypeScript 的好感,所以就決定使用 ts 來實現一個全新的瀏覽器端 md 編輯器。
于是,Vditor 就這樣誕生了。
終于等到你 ?
本來早就想抽出來的,要不在 B3log 開源的幾個項目中維護很頭痛。以后只需要維護一個,然后升級以下就好了。
晚點也在我的項目上試試,現在的 Markdown 編輯器不是功能不全就是 bug 多或者不維護
謝謝支持
哈哈,Vditor 很棒!
https://github.com/b3log/vditor/issues/4 多謝
在焦點處插入內容應該是 insertValue 吧
此鏈接 404
文字錯誤:接觸編輯器禁用,「接觸」->「解除」
前端是這樣傳送的