vue配置bytemd(掘金同款MarkDown插件)

911 阅读2分钟

官方链接:github.com/bytedance/b…

安装

npm install @bytemd/vue -S

安装插件

图片.png 以上若无特殊需要可以不安装

引入方式

图片.png Editor为左侧编辑框,Viewer为右侧查看框(可独立使用)

<template>
    <Editor
        class="editos"
        :value="value"
        :plugins="plugins"
        :locale="zhHans"
        @change="handleChange"
        :uploadImages="uploadImage"
    />

    <Viewer
        class="viewer"
        @change="viewChange"
        :tabindex="2"
        :sanitize="23"
        :plugins="plugins"
        :locale="zhHans">
    </Viewer>
</<template>
import { Editor, Viewer } from '@bytemd/vue'
components: { Editor, Viewer },
data() {
    return {
        value: '', // 获取的内容
        zhHans, // 简体中文
        plugins,
        title:'',
    }
},

导入中文包与掘金同款样式

import zhHans from 'bytemd/locales/zh_Hans.json //中文包

import 'bytemd/dist/index.css' // 导入编辑器样式

import 'juejin-markdown-themes/dist/juejin.min.css'//掘金同款样式

图片展示

插入图片时会触发uploadImage方法

async uploadImage(files) {
    console.log(files)
    const res = await this.upload(files)
    return [
        {
            title: files.map((i) => i.name),
            url: res.url,
        },
    ]
},
//图片上传到服务器
async upload(files) {
    let FormDatas = new FormData();
    FormDatas.append('file[]', files[0])
    const res = await axios({
        method: 'post',
        headers: {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        showLoad: 1,
        },
        url: '/api/system/common/upload.html',
        data: FormDatas,
    })
    return res.data.data[0]
},

难点问题

目录生成

react 可参考github.com/bytedance/b… , vue则需自己写

官方提供 getProcessor方法 可打印出h5文本数组 图片.png

复制问题

从掘金复制文章过来时,插件没有自动转化成Markdown语法,参考资料使用 TurndownService 安装

import TurndownService from 'turndown';//html转md

监听粘贴事件

document.addEventListener('paste', function (event) {
    that.SetHtml(event);
});
//转markdown语法
async SetHtml(e) {
    e.preventDefault();
    const list = e.clipboardData.items;
    for (let i = 0; i < list.length; i++) {
        if (list[i].kind === 'string' && list[i].type.match('^text/html')) {
            const h = await new Promise(t => list[i].getAsString(e => t(e)));
            const ts = new TurndownService()
            this.value = ts.turndown(h)
        }
    }
}

效果如下 图片.png

附源码

<template>
    <Editor
        class="editos"
        :value="value"
        :plugins="plugins"
        :locale="zhHans"
        @change="handleChange"
        :uploadImages="uploadImage"
    />

    <Viewer
        class="viewer"
        @change="viewChange"
        :tabindex="2"
        :sanitize="23"
        :plugins="plugins"
        :locale="zhHans">
    </Viewer>
</<template>
<script>
import axios from 'axios'
import { Editor, Viewer } from '@bytemd/vue'
import zhHans from 'bytemd/locales/zh_Hans.json'//中文包
import 'juejin-markdown-themes/dist/juejin.min.css'//掘金样式
export default {
    components: { Editor, Viewer, editQuestionDialog },
    data() {
        return {
            value: '', // 获取的内容
            zhHans, // 简体中文
            plugins,
            title:'',
            dialogVisible:false
        }
    },
    mounted(){
        const that = this
        //监听粘贴事件
        document.addEventListener('paste', function (event) {
            that.SetHtml(event);
        });
    },

    methods: {
        // 获取书写文档内容
        handleChange(v) {
            this.value = v
            localStorage.setItem('md',this.value)
        },
        viewChange(v){
            console.log(v)
        },
        async uploadImage(files) {
            console.log(files)
            const res = await this.upload(files)
            return [
                {
                    title: files.map((i) => i.name),
                    url: res.url,
                },
            ]
        },
        //图片上传到服务器
        async upload(files) 
            let FormDatas = new FormData();
            FormDatas.append('file[]', files[0])
            const res = await axios({
                method: 'post',
                headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                token: getStore('systemMember').token
                    ? getStore('systemMember').token
                    : '',
                showLoad: 1,
                },
                url: '/api/system/common/upload.html',
                data: FormDatas,
            })
            return res.data.data[0]
        },
        //转markdown语法
        async SetHtml(e) {
            e.preventDefault()
            const list = e.clipboardData.items;
            for (let i = 0; i < list.length; i++) {
                if (list[i].kind === 'string' && list[i].type.match('^text/html')) {
                    const h = await new Promise(t => list[i].getAsString(e => t(e)));
                    const ts = new TurndownService()
                    this.value = ts.turndown(h)
                }
            }
        }
    },
}