我熬夜开发了一款简约实用、支持多平台的Markdown在线编辑器(开源)

简介: 我熬夜开发了一款简约实用、支持多平台的Markdown在线编辑器(开源)

前言


之前,一直想开发一款属于自己的Markdown编辑器,主要是自己平常写文章可以更加灵活操作,另外扩宽自己的视野也是非常不错的选择啊!所以在周末就决定玩耍一番。首先我调研了很多线上热门的md编辑器,都很优秀。不为超过他们,主要自己用着舒服点。这篇文章主要是记录下我是如何从0到1是完成一款还算拿得出手的Markdown编辑器。


完成项目一览


微信截图_20220506142906.png

微信截图_20220506142918.png


调研Markdown编辑器


国内、国外关于Markdown编辑器有很多。


  • editor.md


网址:https://pandao.github.io/editor.md/


是一款开源的、可嵌入的 Markdown 在线编辑器(组件),基于 CodeMirror、jQuery 和 Marked 构建。这个组件好像是国内开发的,个人之前用着还可以。


  • typora


网址:https://www.typora.io/


Typora是一款免费的轻量级Markdown编辑器,它没有Mou,Haroopad等Markdown编辑器那么大名鼎鼎,算是较为小众的一款产品。 凭良心说话,我用过的Markdown编辑器也有好几款,其中包括:小书匠,Haroopad,Atom等,但Typora是最合我心意的一款编辑器了,其轻量、快速、易于上手,使用起来简直不要太舒服!!


  • tui-editor


网址:https://ui.toast.com/tui-editor


这是一款Markdown组件,通过调研决定用它。为什么?确认过眼神~


技术栈


  • Vue.js
  • tui-editor


实战


确定好技术栈之后,我们就得脚踏实地地干活了。


1. 搭建Vue脚手架


我们会使用VueCLI搭建一个最基础的项目,这里暂时不需要Vue-routerVuex这些插件,所以尽可能轻装。


2. 创建编辑器组件


我们会在components文件目录下创建一个Editor.vue文件,这个文件也就是我们的主战场,大部分操作都会在这个文件。


3. 配置编辑器组件


在配置编辑器时,有以下几点使我非常困惑,以致于花费了大量时间。


  1. 代码没有被高亮
  2. 语言不是中文
  3. 编辑器样式有问题


以上这几个问题通过以下措施才得以解决:


  1. 通过阅读文档:https://nhn.github.io/tui.editor/latest/


  1. 访问Github网站:https://github.com/nhn/tui.editor


Editor.vue


<template>
  <div class="main">
    <div id="editor"></div>
  </div>
</template>
<script>
import Editor from "@toast-ui/editor";
import hljs from "highlight.js";
import codeSyntaxHighlight from "@toast-ui/editor-plugin-code-syntax-highlight";
import '@toast-ui/editor/dist/i18n/zh-cn.js';
import "highlight.js/styles/github.css";
import "codemirror/lib/codemirror.css"; // Editor's Dependency Style
import "@toast-ui/editor/dist/toastui-editor.css"; // Editor's Style
import "@/styles/index.css";
export default {
  components: {},
  data() {
    return {
      editor: null
    };
  },
  mounted() {
    this.editor = new Editor({
      el: document.getElementById("editor"),
      plugins: [[codeSyntaxHighlight, {hljs}]],
      previewStyle: "vertical",
      height: "100vh",
      initialEditType: "markdown",
      minHeight: "200px",
      initialValue: "",
      placeholder: "你想写点什么...",
      language:'zh-CN',
      useCommandShortcut: true,
      useDefaultHTMLSanitizer: true,
      usageStatistics: false,
      hideModeSwitch: false,
      viewer: true,
      toolbarItems: [
        "heading",
        "bold",
        "italic",
        "strike",
        "divider",
        "hr",
        "quote",
        "divider",
        "ul",
        "ol",
        "task",
        "indent",
        "outdent",
        "divider",
        "table",
        "image",
        "link",
        "divider",
        "code",
        "codeblock",
      ],
    });
    this.editor.getUI().getToolbar().removeItem("21");
  },
};
</script>


看似上面几行代码,但是也是很费劲才得以完成。


增加功能


首先,我开发这个程序的初衷是更好地方便自己写文章,所以,我定下了这几个需求:


  1. 可复制HTML格式文本,方便复制到微信公众号
  2. 可复制Markdown文本,方便可以复制到稀土掘金、csdn这些博客网站上发布
  3. 可下载Markdown文件,更加方便保存和移动


因篇幅原因,先奉上主要逻辑代码。这里我使用了clipboard这个将文本复制到剪贴板的插件。网址:https://clipboardjs.com/。 另外,downloadBlobAsFile方法主要是创建Blob对象,然后通过a标签的download属性进行下载。


downloadBlobAsFile.js


export default function downloadBlobAsFile(data, filename) {
    const contentType = 'application/octet-stream';
    if (!data) {
        console.error(' No data');
        return;
    }
    if (!filename) {
        filename = 'filetodonwload.txt';
    }
    if (typeof data === 'object') {
        data = JSON.stringify(data, undefined, 4);
    }
    let blob = new Blob([data], {type: contentType});
    let e = document.createEvent('MouseEvents');
    let a = document.createElement('a');
    a.download = filename;
    a.href = URL.createObjectURL(blob);
    a.dataset.downloadurl = [contentType, a.download, a.href].join(':');
    e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    a.dispatchEvent(e);
}


Editor.vue


<template>
  <div class="main">
    <div class="tools">
      <el-button
          size="mini"
          type="primary"
          @click="drawer = true"
      >工具</el-button>
      <el-button
          size="mini"
          type="primary"
          @click="aboutView = true"
      >关于</el-button>
      <el-dialog
          :title="'工具'"
          :visible.sync="drawer"
          :append-to-body="true"
      >
        <div class="tool-innter">
          <el-button type="primary" @click="getHtml" class="htmlbtn"
          >复制HTML
          </el-button
          >
          <el-button type="primary" @click="getMd" class="mdbtn"
          >复制MarkDown
          </el-button
          >
          <el-button type="primary" @click="downloadMd" class="downloadbtn"
          >下载MarkDown
          </el-button
          >
        </div>
      </el-dialog>
      <el-dialog
          :title="'关于'"
          :visible.sync="aboutView"
          :append-to-body="true"
      >
        <h3>Simple·MarkDown编辑器</h3>
        <ul class="functionList">
          <li v-for="(item,index) in functionList" :key="index">
            {{item}}
          </li>
        </ul>
        <h3>作者</h3>
        <ul class="functionList">
          <li v-for="(item,index) in authorList" :key="index">{{item}}</li>
        </ul>
        <div class="wxcode">
          <img src="../assets/wxcode.jpeg" alt="">
        </div>
      </el-dialog>
    </div>
    <div id="editor"></div>
  </div>
</template>
<script>
import Editor from "@toast-ui/editor";
import Clipboard from "clipboard";
import hljs from "highlight.js";
import codeSyntaxHighlight from "@toast-ui/editor-plugin-code-syntax-highlight";
import '@toast-ui/editor/dist/i18n/zh-cn.js';
import downloadBlobAsFile from "../utils/download";
import "highlight.js/styles/github.css"; //https://github.com/highlightjs/highlight.js/tree/master/src/styles
import "codemirror/lib/codemirror.css"; // Editor's Dependency Style
import "@toast-ui/editor/dist/toastui-editor.css"; // Editor's Style
import "@/styles/index.css";
export default {
  components: {},
  data() {
    return {
      editor: null,
      drawer: false,
      aboutView: false,
      functionList:['页面简约','功能实用','支持稀土掘金、CSDN、微信公众号、知乎','可复制HTML、MarkDown','可下载MarkDown文件'],
      authorList:['作者:Vam的金豆之路','欢迎关注我的公众号:前端历劫之路','我创建了一个技术交流、文章分享群,群里有很多大厂的前端大佬,关注公众号后,点击下方菜单了解更多即可加我微信,期待你的加入']
    };
  },
  methods: {
    // 复制HTML
    getHtml() {
      const clipboard = new Clipboard(".htmlbtn", {
        target: () => this.editor.preview.el,
      });
      clipboard.on("success", () => {
        this.$message({
          message: "复制成功",
          type: "success",
        });
        clipboard.destroy();
      });
      clipboard.on("error", () => {
        this.$message.error("复制失败");
        clipboard.destroy();
      });
    },
    // 复制Markdown
    getMd() {
      const clipboard = new Clipboard(".mdbtn", {
        text: () => this.editor.getMarkdown(),
      });
      clipboard.on("success", () => {
        this.$message({
          message: "复制成功",
          type: "success",
        });
        clipboard.destroy();
      });
      clipboard.on("error", () => {
        this.$message.error("复制失败");
        clipboard.destroy();
      });
    },
    // 下载Markdown
    downloadMd() {
      if (this.editor.getMarkdown().trim()) {
        downloadBlobAsFile(this.editor.getMarkdown(), "unnamed.md");
      } else {
        this.$message.error("下载失败");
      }
    },
  },
  mounted() {
    this.editor = new Editor({
      el: document.getElementById("editor"),
      plugins: [[codeSyntaxHighlight, {hljs}]],
      previewStyle: "vertical",
      height: "100vh",
      initialEditType: "markdown",
      minHeight: "200px",
      initialValue: "",
      placeholder: "你想写点什么...",
      language:'zh-CN',
      useCommandShortcut: true,
      useDefaultHTMLSanitizer: true,
      usageStatistics: false,
      hideModeSwitch: false,
      viewer: true,
      toolbarItems: [
        "heading",
        "bold",
        "italic",
        "strike",
        "divider",
        "hr",
        "quote",
        "divider",
        "ul",
        "ol",
        "task",
        "indent",
        "outdent",
        "divider",
        "table",
        "image",
        "link",
        "divider",
        "code",
        "codeblock",
      ],
    });
    this.editor.getUI().getToolbar().removeItem("21");
  },
};
</script>


针对微信公众号进行样式优化


::v-deep是深度作用选择器,主要是为了覆盖原有的样式所用。


::v-deep ul li {
  list-style-type: disc !important;
}
::v-deep ol li {
  list-style-type: decimal !important;
}
::v-deep ul li::before, ::v-deep ol li::before {
  content: none;
}
::v-deep .tui-editor-contents p>code{
  background-color: #fff5f5;
  color: #ff502c;
}
::v-deep .tui-editor-contents pre {
  width: 100%;
  overflow: auto;
}


线上体验


https://www.maomin.club/site/mdeditor/


结语


谢谢阅读,希望没有浪费你的时间。


源码地址:


https://github.com/maomincoding/simpleMdEditor


如果对你有帮助,欢迎Star~



微信截图_20220506142906.png微信截图_20220506142906.png

相关文章
|
2月前
|
Ubuntu Linux 测试技术
Linux系统之部署轻量级Markdown文本编辑器
【10月更文挑战第6天】Linux系统之部署轻量级Markdown文本编辑器
143 1
Linux系统之部署轻量级Markdown文本编辑器
|
9天前
|
人工智能 文字识别 数据挖掘
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
MarkItDown 是微软开源的多功能文档转换工具,支持将 PDF、PPT、Word、Excel、图像、音频等多种格式的文件转换为 Markdown 格式,具备 OCR 文字识别、语音转文字和元数据提取等功能。
78 9
MarkItDown:微软开源的多格式转Markdown工具,支持将PDF、Word、图像和音频等文件转换为Markdown格式
|
28天前
|
人工智能 移动开发 前端开发
Markdown-to-Image:开源的在线 Markdown 转海报编辑器
Markdown-to-Image 是一款开源的在线 Markdown 转海报编辑器,能够将 Markdown 文本内容转换为图像,适用于创建社交媒体帖子、海报和其他视觉内容。该工具支持多种输出格式,并允许用户自定义样式,适用于多种应用场景。
75 4
Markdown-to-Image:开源的在线 Markdown 转海报编辑器
|
1月前
|
前端开发
业余时间开发了个海报编辑器
为了满足撰写博客或录制教程视频时对高质量海报的需求,我利用业余时间开发了一款海报编辑器。第一版功能简单,支持固定尺寸、黑底白字的标题。后来经过优化,增加了背景图、模糊效果、文字样式调整等功能,使海报更具吸引力。目前该编辑器已上线,欢迎大家试用并反馈。[访问海报编辑器](https://tool.share888.top/#/poster)
77 6
业余时间开发了个海报编辑器
|
1月前
|
存储 安全 关系型数据库
Blossom:开源私有部署的markdown笔记软件
Blossom 是一款功能强大的开源笔记软件,支持私有部署,可将笔记、图片、个人计划等数据保存在自己的服务器中,并实现实时同步。它还具备动态博客功能,方便记录和分享内容。Blossom 支持多种设备,提供完善的文件管理、快速迁移和丰富的附加功能,是个人知识管理和博客展示的理想选择。
72 7
Blossom:开源私有部署的markdown笔记软件
|
4月前
|
存储 安全 数据安全/隐私保护
Django 后端架构开发:富文本编辑器权限管理与 UEditor 、Wiki接入,实现 Markdown 文本编辑器
Django 后端架构开发:富文本编辑器权限管理与 UEditor 、Wiki接入,实现 Markdown 文本编辑器
182 0
|
3月前
|
JavaScript 前端开发 API
vue3 v-md-editor markdown编辑器(VMdEditor)和预览组件(VMdPreview )的使用
本文介绍了如何在Vue 3项目中使用v-md-editor组件库来创建markdown编辑器和预览组件。文章提供了安装步骤、如何在main.js中进行全局配置、以及如何在页面中使用VMdEditor和VMdPreview组件的示例代码。此外,还提供了一个完整示例的链接,包括编辑器和预览组件的使用效果和代码。
vue3 v-md-editor markdown编辑器(VMdEditor)和预览组件(VMdPreview )的使用
|
2月前
|
运维 Java Linux
【运维基础知识】掌握VI编辑器:提升你的Java开发效率
本文详细介绍了VI编辑器的常用命令,包括模式切换、文本编辑、搜索替换及退出操作,帮助Java开发者提高在Linux环境下的编码效率。掌握这些命令,将使你在开发过程中更加得心应手。
42 2
|
3月前
|
API C# Windows
一个.NET开源、现代、轻量级的文本编辑器
一个.NET开源、现代、轻量级的文本编辑器
|
4月前
|
前端开发 Python
60行Python代码开发在线markdown编辑器
60行Python代码开发在线markdown编辑器

热门文章

最新文章