0.0.2 • Published 7 months ago

stock-vue-meditor v0.0.2

Weekly downloads
-
License
MIT
Repository
-
Last release
7 months ago

好久没维护过这个项目了,vue的语法已经忘干净了😅,使用过程中有问题,建议直接把源码拉下来改动,我不是个合格的开源作者。

简介

一款使用marked和highlight.js开发的一款markdown编辑器,除常见markdown语法外,支持快捷输入、图片粘贴、代码复制、全屏编辑、预览等功能。

使用起来简单方便,只需几行代码,即可在你的页面上引入一个markdown编辑器,编辑区支持像专业编辑器那样。

编辑器涵盖了常用的markdown编辑器功能,可通过已有属性进行配置,对编辑器功能和样式进行基本的配置,也可根据需求进行深度定制。

项目地址

文档地址

示例 image.png

特点

  • 使用简单,只需要安装npm包,引入项目即可使用,不需要繁琐的初始化配置。
  • 方便扩展,根据实际需求,支持常见的功能配置,也可根据实际需求进行深度定制。
  • 体积小,加载速度快,npm包删除了highlight.js和codemirror里的依赖。
  • 灵活的主题,默认支持四种代码块风格,也可根据实际需求定制自己的主题样式
  • 功能强大,支持专业版的编辑器,使用codemirror实现编辑窗口,可识别markdown语法
  • 键盘事件监听,如保存、粘贴、回车时上次输入语法判断等
  • 可扩展性强,除了提供的属性配置编辑器,也可直接在原有组件基础上进行二次开发

实现思路

通过监听文本输入区域内内容的变化,实时将输入的markdown语法进行编译,并渲染到预览区域。

编辑器大致分为头部菜单栏、左侧内容输入区域、右侧预览区域三个部分。 头部菜单主要为定自定义标题区域和菜单按钮,菜单按钮可通过配置文件进行显示和隐藏;左侧编辑区域,简单版使用textarea开发,满足基本需求, 专业版使用codemirror开发,编辑区域支持手动输入文本和通过头部菜单插入;右侧预览区域可实时预览输入文本,并可通过菜单按钮,进行编辑区域和预览区域的切换。

安装方式

使用npm安装

  1. 安装依赖
npm i -S vue-meditor

将组件复制到项目内

  1. 将git仓库代码拉到本地
git clone https://github.com/zhaoxuhui1122/vue-markdown.git
  1. 复制src文件夹下内容至components文件夹下

在项目使用

npm包安装时

简单版

import Markdown from 'vue-meditor'

专业版

import { MarkdownPro } from 'vue-meditor'

预览组件

import { MarkdownPreview } from 'vue-meditor'

复制组件到本地时(推荐)

简单版

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链接
imageimage
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

license: MIT