vue-markdown編輯器

簡介

一款使用marked和highlight.js開發的一款markdown編輯器,除常見markdown語法外,支持快捷輸入、圖片粘貼、代碼複製、全屏編輯、預覽等功能。javascript

使用起來簡單方便,只需幾行代碼,便可在你的頁面上引入一個markdown編輯器,編輯區支持像專業編輯器那樣。php

編輯器涵蓋了經常使用的markdown編輯器功能,可經過已有屬性進行配置,對編輯器功能和樣式進行基本的配置,也可根據需求進行深度定製。css

項目地址

文檔地址

示例 html

image.png

特色

  • 使用簡單,只須要安裝npm包,引入項目便可使用,不須要繁瑣的初始化配置。
  • 方便擴展,根據實際需求,支持常見的功能配置,也可根據實際需求進行深度定製。
  • 體積小,加載速度快,npm包刪除了highlight.js和codemirror裏的依賴。
  • 靈活的主題,默認支持四種代碼塊風格,也可根據實際需求定製本身的主題樣式
  • 功能強大,支持專業版的編輯器,使用codemirror實現編輯窗口,可識別markdown語法
  • 鍵盤事件監聽,如保存、粘貼、回車時上次輸入語法判斷等
  • 可擴展性強,除了提供的屬性配置編輯器,也可直接在原有組件基礎上進行二次開發

實現思路

經過監聽文本輸入區域內內容的變化,實時將輸入的markdown語法進行編譯,並渲染到預覽區域。vue

編輯器大體分爲頭部菜單欄、左側內容輸入區域、右側預覽區域三個部分。 頭部菜單主要爲定自定義標題區域和菜單按鈕,菜單按鈕可經過配置文件進行顯示和隱藏;左側編輯區域,簡單版使用textarea開發,知足基本需求, 專業版使用codemirror開發,編輯區域支持手動輸入文本和經過頭部菜單插入;右側預覽區域可實時預覽輸入文本,並可經過菜單按鈕,進行編輯區域和預覽區域的切換。java

安裝方式

使用npm安裝

  1. 安裝依賴
npm i -S vue-meditor
複製代碼

將組件複製到項目內

  1. 將git倉庫代碼拉到本地
git clone https://github.com/zhaoxuhui1122/vue-markdown.git
複製代碼
  1. 複製src文件夾下內容至components文件夾下

在項目使用

npm包安裝時

簡單版python

import Markdown from 'vue-meditor'
複製代碼

專業版react

import { MarkdownPro } from 'vue-meditor'
複製代碼

預覽組件git

import { MarkdownPreview } from 'vue-meditor'
複製代碼

複製組件到本地時(推薦)

簡單版github

import Markdown from '@/components/markdown/...';
複製代碼

專業版

import MarkdownPro from '@/components/markdown/pro';
複製代碼

預覽組件

import MarkdownPreview from '@/components/markdown/preview';
複製代碼

在頁面內使用

<template>
    <div class="markdown">
        <Markdown/>
    </div>
</template>

<script>
    import Markdown from 'vue-meditor';
    
    export default {
        name: "markdown",
        components: {
            Markdown
        }
    }
</script>
複製代碼

API

編輯器基本屬性

value

  • Type: String/Number
  • Default: ''

編輯器輸入的文本,支持經過v-dodel數據雙向綁定設置編輯器內容和獲取編輯器的值。

width

  • Type: String/Number
  • Default: auto

編輯器的初始化寬度。

height

  • Type: Number
  • Default: 600

編輯器的初始化高度。

bordered

  • Type: Boolean
  • Default: true

編輯器是否含有邊框。

toolbars

  • Type: Object
  • Default: 參見下表

頭部菜單按鈕,經過設置true or false控制決定是否顯示,目前配置支持持控制按鈕顯示隱藏,後續將支持根據配置顯示排列順序。

名稱 說明 默認是否顯示
strong 粗體
italic 斜體
overline 刪除線
h1 標題1
h2 標題2
h3 標題3
h4 標題4
h5 標題5
h6 標題6
hr 分割線
quote 引用
ul 無序列表
ol 有序列表
code 代碼塊
link 連接
image image
table 表格
checked 已完成列表
notChecked 未完成列表
preview 預覽
split 分屏模式切換
print 打印
theme 主題切換
fullscreen 全屏
exportmd 導出爲*.md文件
importmd 導入本地*.md文件
save 保存按鈕
clear 清空內容

theme

  • Type: String
  • Default: light

編輯器代碼塊主題,目前支持lightdarkoneDarkgitHub四種代碼塊風格,可經過自定義theme並修改樣式文件進行主題定製。

自定義theme時,預覽區域的會增長一個爲markdown-theme-[theme]class

autoSave

  • Type: Boolean
  • Default: false

是否開啓自動保存,設置爲開啓時可經過綁定on-save事件獲取編輯器內的值和代碼塊主題。

<Markdown @on-save="handleOnSave"/>
複製代碼
handleOnSave({value, theme}){
        console.log(value, theme);
    }
複製代碼

interval

  • Type: Number
  • Default: 10000

自動保存間隔時間,單位:mm,默認10000mm,須要autoSave = true時纔有效。

exportFileName

  • Type: String
  • Default: unnamed

導出的md文件名稱,默認unnamed.md。

markedOptions

  • Type: Object
  • Default: {}

marked配置項,能夠根據需求自定義。

<Markdown :markedOptions="{baseUrl:'http://***.oss-cn-shanghai.aliyuncs.com/'}"/>
複製代碼

isPreview

  • Type: Boolean
  • Default: false

是不是預覽模式,開啓時可做爲一個預覽組件使用,與預覽組件功能一致。

copyCode

  • Type: Boolean
  • Default: true

是否支持複製代碼塊內的內容。

copyBtnText

  • Type: String
  • Default: 複製代碼

複製代碼按鈕顯示文字。

預覽組件基本屬性

initialValue

  • Type: String/Number
  • Default: ''

預覽組件初始化內容,支持動態更新。

theme

  • Type: String
  • Default: light

代碼塊主題,與編輯器編輯器代碼塊主題一致。

markedOptions

  • Type: Object
  • Default: {}

marked配置項,與編輯器內該配置一致。

copyCode

  • Type: Boolean
  • Default: true

是否支持複製代碼塊內的內容。

copyBtnText

  • Type: String
  • Default: 複製代碼

複製代碼按鈕顯示文字。

on-ready

編輯器初始化完成時觸發,返回值爲Object,包含組件自己和insertContent方法。

on-save

編輯器保存事件,自動保存或者手動保存時觸發,支持ctrl+scommand+s觸發保存,返回值類型爲Object,包含當前輸入值value和選擇的代碼塊主題theme

on-paste-image

監聽編輯器粘貼圖片事件,在編輯區域內手動粘貼圖片時觸發,可用於支持粘貼插入圖片文件,返回file文件,上傳文件後可結合on-ready事件內返回的insertContent插入圖片。

on-copy

複製代碼塊內容,觸發時返回當前代碼塊的text,copyCode開啓時纔有效。

二次開發

粘貼插入圖片

on-paste-image雖然能夠支持圖片粘貼事件的監聽,但不會處理圖片上傳至服務器並將連接插入編輯器這段邏輯。

目前若是想要支持粘貼插入圖片,須要在on-paste-image方法裏上傳圖片文件,拿到圖片地址後,使用on-ready方法裏返回的insertContent方法插入圖片。

上述操做顯得過於複雜,能夠直接在源碼裏擴展mixins裏的handlePaste方法,圖片上傳完成後,直接調用this.insertContent方法插入圖片。

修改/markdown/mixins/common.js

handlePaste(_, e) {// 粘貼圖片
    const { clipboardData = {} } = e;
    const { types = [], items } = clipboardData;
    let item = null;
    for (let i = 0; i < types.length; i++) {
        if (types[i] === 'Files') {
            item = items[i];
            break;
        }
    }
    if (item) {
        const file = item.getAsFile();
        if (/image/gi.test(file.type)) {
            e.preventDefault();
            // 1.上傳操做
            // 2.插入圖片 this.insertContent(`![image](imgUrl)`)
        }
    }
}
複製代碼

支持流程圖、甘特圖等語法

目前編輯器只支持常見code語法,若是須要實現如流程圖等功能,須要進一步擴展,以實現一個簡單的流程圖爲例,具體實現思路以下:

默認狀況下,markedjs會使用renderer.code方法對輸入的代碼塊進行解析,並會藉助highlight.js支持語法高亮。 能夠將流程圖語法輸入到代碼塊內,並標明語言,重寫marked.Renderer的code解析方法,結合結合flowchart.js路程圖代碼進行解析,返回文本內容。

修改`/markdown/libs/js/simple.js

import hljs from './hljs';
import index from 'index';
import {parse} from 'flowchart.js'

hljs.initHighlightingOnLoad();

const renderer = new index.Renderer();
renderer.code = (code, language) => {
    if (language === 'flow') {// 流程圖
        const dom = document.createElement('div');
        const flowchart = parse(code);
        flowchart.drawSVG(dom, {/*相關配置*/});
        return  dom.innerHTML;
    } else {// 默認解析
        return `<pre class="hljs"><code class="${language}">${hljs.highlightAuto(code).value}</code></pre>`
    }
}
export default index.setOptions({
    renderer,
    gfm: true,
    tables: true,
    breaks: false,
    pedantic: false,
    sanitize: false,
    smartLists: true,
    highlight: function (code) {
        return hljs.highlightAuto(code).value;
    }
})
複製代碼

自定義markdown語法轉換

項目內使用的`index.js均爲其默認配置功能,如須要特殊轉換,可重寫其內部的解析方法,即重寫其renderer相關方法 參考文檔

自動生成文檔目錄

預覽區域和文檔預覽組件暫不支持自動生成目錄,實現自動生成目錄思路目前想到的大體有

  • 重寫renderer.heading 方法,爲生成的標題添加id,輸入特定快捷鍵,如[TOC]時,查找預覽區域內的的全部標題標籤,分析等級關係,生成目錄標籤

icon替換

項目內全部的icon和命名參考/assets/font/index.html,替換時需注意,預覽區域的checkbox爲icon,注意一併替換, 修改/assets/css/index.less內的input[type="checkbox"]:after樣式。

代碼體積優化

公共代碼提取

npm包構建時,三個組件徹底獨立,沒有抽離公共文件,因此,當同一個項目內引入其中的兩個或三個組件都引入時,存在必定的重複代碼, 主要爲highlight.jsmarkediconfont、css樣式幾個部分。

解決方式:將組件複製到本地項目,打包時將這些文件做爲公共文件抽離出來。

注意:三個組件中使用的iconfont爲同一套,若是隻是單純的使用preview組件, 將會引入整個項目所使用的iconfont,可刪除iconfont的引入, 重寫input[type="checkbox"]的樣式,preview組件體積將會減小一半,樣式文件位於markdown/assets/css/index.less

codemirror體積優化

codemirror主要分爲主文件、mode相關文件和樣式文件,主文件體積異常的大,mode文件目前只選用了css/jsvascript/markdown/meta/xml五個文件, 其中markdown.js和meta.js爲必須引用的,項目中已將常見的編程語言代碼風格定義爲css/js/xml之一,例如less/sass/scss按照css規則解析,html/vue按照xml規則解析。 優化可從一下方面入手

  • 減小codemirror主文件體積
  • 減小引用的mode依賴

highlight.js體積優化

highlight.js本來體積也是較大的,主要緣由爲,編譯時爲支持各類代碼語言,引入了相應的解析文件, 項目內已根據常見的代碼語言進行了一次篩選,進行按需引入,可根據自身需求,再次對引用文件進行刪減

參見src/markdown/libs/js/hljs.js,目前支持的語言有

import hljs from 'highlight.js/lib/highlight'

import javascript from 'highlight.js/lib/languages/javascript'
import java from 'highlight.js/lib/languages/java';
import css from 'highlight.js/lib/languages/css';
import less from 'highlight.js/lib/languages/less';
import go from 'highlight.js/lib/languages/go';
import markdown from src;
import php from 'highlight.js/lib/languages/php';
import python from 'highlight.js/lib/languages/python';
import ruby from 'highlight.js/lib/languages/ruby';
import stylus from 'highlight.js/lib/languages/stylus';
import typescript from 'highlight.js/lib/languages/typescript';
import xml from 'highlight.js/lib/languages/xml';

const languages = {
    javascript,
    java,
    css,
    less,
    markdown,
    go,
    php,
    python,
    ruby,
    stylus,
    typescript,
    xml
}
Object.keys(languages).forEach(key => {
    hljs.registerLanguage(key, languages[key])
})

export default hljs;
複製代碼

專業版編輯器codemirror/simple.js

優化思路:無

iconfont 體積優化

只須要preview組件時,避免引入全部icon,參考功能擴展裏icon替換方法。

升級路線

  • 普通版編輯器對選中文本進行操做功能
  • 文檔目錄功能
  • 優化專業版編輯器體積
  • react版開發
  • ...

問題反饋

對於功能上的缺陷、使用方法和但願擴展的功能,能夠提 Issues

相關文章
相關標籤/搜索