整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

简单几步学会使用富文本编辑器Editormd

们经常可以看到各个博客网站中用于编辑文章的富文本编辑器,在富文本编辑器中,我们可以对我们的编辑内容样式进行设置。富文本编辑器一般是通过插件来实现的,我们只需要在页面中配置一下插件提供的一些API即可。

本例中使用Editormd来演示如何配置使用富文本编辑器。

Editormd简介

Editormd是国内开源的一款在线Markdown编辑器,可嵌入的 Markdown 在线编辑器(组件),基于 CodeMirror、jQuery 和 Marked 构建。

主要特性

支持“标准”Markdown / CommonMarkGithub风格的语法,也可变身为代码编辑器。

  • 支持实时预览、图片(跨域)上传、预格式文本/代码/表格插入、代码折叠、搜索替换、只读模式、自定义样式主题和多语言语法高亮等功能。
  • 支持ToC(Table of Contents)、Emoji表情、Task lists、@链接等Markdown扩展语法。
  • 支持TeX科学公式(基于KaTeX)、流程图 Flowchart 和 时序图 Sequence Diagram。
  • 支持识别和解析HTML标签,并且支持自定义过滤标签解析,具有可靠的安全性和几乎无限的扩展性。
  • 支持 AMD / CMD 模块化加载(支持 Require.js & Sea.js),并且支持自定义扩展插件。
  • 兼容主流的浏览器(IE8+)和Zepto.js,且支持iPad等平板设备。
  • 支持自定义主题样式。

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

创建文章表

在使用富文本编辑器之前,先来创建一个文章表article,这里只添加了最基本的几个字段, 以后想要扩展的话还可以添加标签、时间、浏览量、点赞、评论等字段。建表SQL如下:

CREATE TABLE article(
    id int(10) NOT NULL AUTO_INCREMENT COMMENT '文章唯一id',
    author varchar(50) NOT NULL COMMENT '作者',
    title varchar(100) NOT NULL COMMENT '标题',
    content longtext NOT NULL COMMENT '文章内容'
    PRIMARY KEY (id)
)ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

建完表,我们就可以开始编写代码来使用富文本编辑器了。

配置使用

1、创建一个SpringBoot项目,配置数据库连接,我们这里连接的是MyBatis(注意MySQL8需要在url中配置时区)。

spring:
  datasource:
    username: root
    password: 123456
    #?serverTimezone=UTC解决时区的报错
    url: jdbc:mysql://localhost:3306/springboot?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
  thymeleaf:
    cache: false
​
mybatis:
  mapper-locations: classpath:com/wunian/mapper/*.xml
  type-aliases-package: com.wunian.pojo

2、导入Editormd静态资源,静态资源的目录结构如下图所示。

3、编写文章编辑页面editor.html,引入Editormd的CSS和js文本,添加Editormd配置。

<!DOCTYPE html>
<html class="x-admin-sm" lang="zh" xmlns:th="http://www.thymeleaf.org">
​
<head>
    <meta charset="UTF-8">
    <title>及时雨的Blog</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi" />
    <!--Editor.md-->
    <link rel="stylesheet" th:href="@{/editormd/css/editormd.css}"/>
    <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon" />
</head>
<!--写博客页面-->
<body>
​
<div class="layui-fluid">
    <div class="layui-row layui-col-space15">
        <div class="layui-col-md12">
            <!--博客表单-->
            <form name="mdEditorForm">
​
                <div>
                    标题: <input type="text" name="title">
                </div>
​
                <div>
                   作者: <input type="text" name="author">
                </div>
​
                <!-- 文章的主体内容 textarea -->
                <div id="article-content">
                    <textarea name="content" id="content" style="display:none;"> </textarea>
                </div>
​
            </form>
​
        </div>
    </div>
</div>
</body>
​
<!--editormd-->
<script th:src="@{/editormd/jquery.min.js}"></script>
<script th:src="@{/editormd/editormd.js}"></script>
​
<script type="text/javascript">
    var testEditor;
    $(function() {
         //这是一个最简单的Editormd配置,往后我们要修改Editormd的
        //功能或者样式,就改这里的配置就可以了
        testEditor = editormd("article-content", {
            width   : "90%",
            height  : 640,
            syncScrolling : "single",
            path    : "../editormd/lib/"
        });
</script>
</html>

4、上面配置的只是最简单的富文本编辑器功能,我们可以添加更多的配置来增加功能。

<script type="text/javascript">
    var testEditor;
​
    //window.onload = function(){ }
    $(function() {
        testEditor = editormd("article-content", {
            width : "95%",
            height : 500,
            syncScrolling : "single",
            path : "../editormd/lib/",
            // 自定义的增强配置!
            saveHTMLToTextarea : true,    // 保存 HTML 到 Textarea
            emoji: true, // 开启表情的功能! 图片的本地配置!
            // theme: "light",//工具栏主题
            // previewTheme: "dark",//预览主题
            // editorTheme: "pastel-on-dark",//编辑主题
            // markdown的配置!
            tex : true,                   // 开启科学公式TeX语言支持,默认关闭
            flowChart : true,             // 开启流程图支持,默认关闭
            sequenceDiagram : true,       // 开启时序/序列图支持,默认关闭,
            //图片上传
            imageUpload : true,
            imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
            imageUploadURL : "/article/file/upload", // 文件上传的处理请求!
            onload : function() {
                console.log('onload', this);
            },
            /*指定需要显示的功能按钮*/
            toolbarIcons : function() {
                return ["undo","redo","|",
                    "bold","del","italic","quote","ucwords","uppercase","lowercase","|",
                    // "h1","h2","h3","h4","h5","h6","|",
                    "list-ul","list-ol","hr","|",
                    "link","reference-link","image","code","preformatted-text",
                    "code-block","table","datetime","emoji","html-entities","pagebreak","|",
                    "goto-line","watch","preview","fullscreen","clear","search","|",
                    //"help","info",
                    "releaseIcon", "index"]
            },
            // 这里的自定义功能就好比,Vue 组件
​
            /*自定义功能按钮,下面我自定义了2个,一个是发布,一个是返回首页*/
            toolbarIconTexts : {
                releaseIcon : "<span bgcolor=\"gray\">发布</span>",
                index : "<span bgcolor=\"red\">返回首页</span>",
            },
​
            /*给自定义按钮指定回调函数*/
            toolbarHandlers:{
                releaseIcon : function(cm, icon, cursor, selection) {
                    //表单提交
                    mdEditorForm.method = "post";
                    mdEditorForm.action = "/article/addArticle";//提交至服务器的路径
                    mdEditorForm.submit();
                },
                index : function(){
                    window.location.href = '/';
                },
            }
        });
    });
</script>

5、由于表情包的加载地址在国外,因此有时候可能加载不出来,我们可以把表情包下载到本地,放到/static/editormd/plugins/emoji-dialog/emoji目录下,并修改editormd.js中的表情加载路径为我们的表情包存放的目录路径。

editormd.emoji     = {
        path  : "../editormd/plugins/emoji-dialog/emoji/",
        ext   : ".png"
};

6、上传图片功能需要进行配置,我们可以在当前项目目录下建立upload文件夹来上传文件(注意这里应该手动建立目录,不要使用代码创建),然后配置一下虚拟路径(需要自定义WebMVC配置类)。

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
​
​
    // 文件保存在真实目录/upload/下,
    // 访问的时候使用虚路径/upload,比如文件名为1.png,就直接/upload/1.png就ok了。
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/upload/**")
                .addResourceLocations("file:"+System.getProperty("user.dir")+"/upload/");
    }
}

7、在Controller中编写文件上传的请求方法。

// MarkDown博客图片上传问题
@RequestMapping("/file/upload")
@ResponseBody
public JSONObject fileUpload(@RequestParam(value = "editormd-image-file", required = true) MultipartFile file, HttpServletRequest request) throws IOException {
    //上传路径保存设置
​
    //获得SpringBoot当前项目的路径:System.getProperty("user.dir")
    String path = System.getProperty("user.dir")+"/upload/";
​
    //按照月份进行分类:
    Calendar instance = Calendar.getInstance();
    String month = (instance.get(Calendar.MONTH) + 1)+"月";
    path = path+month;
​
    File realPath = new File(path);
    if (!realPath.exists()){
        realPath.mkdirs();
    }
​
    //上传文件地址
    System.out.println("上传文件保存地址:"+realPath);
​
    //解决文件名字问题:我们使用uuid;
    String filename = "ks-"+UUID.randomUUID().toString().replaceAll("-", "")+".jpg";
    //通过CommonsMultipartFile的方法直接写文件(注意这个时候)
    file.transferTo(new File(realPath +"/"+ filename));
​
    //给editormd进行回调
    JSONObject res = new JSONObject();
    res.put("url","/upload/"+month+"/"+ filename);
    res.put("success", 1);
    res.put("message", "upload success!");
​
    return res;
}

8、编写文章显示页面article.html,同样需要配置Editormd来正常显示一些MarkDown文本。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title th:text="${article.title}"></title>
</head>
<!--读博客的页面-->
​
<body>
<div>
    <!--文章头部信息:标题,作者,最后更新日期,导航-->
    <h2 style="margin: auto 0" th:text="${article.title}"></h2>
    作者:<span style="float: left" th:text="${article.author}"></span>
    <!--文章主体内容-->
    <div id="doc-content">
        <textarea style="display:none;" placeholder="markdown" th:text="${article.content}"></textarea>
    </div>
​
</div>
​
<!--固定editormd依赖! -->
<link rel="stylesheet" th:href="@{/editormd/css/editormd.preview.css}"/>
<script th:src="@{/editormd/jquery.min.js}"></script>
<script th:src="@{/editormd/lib/marked.min.js}"></script>
<script th:src="@{/editormd/lib/prettify.min.js}"></script>
<script th:src="@{/editormd/lib/raphael.min.js}"></script>
<script th:src="@{/editormd/lib/underscore.min.js}"></script>
<script th:src="@{/editormd/lib/sequence-diagram.min.js}"></script>
<script th:src="@{/editormd/lib/flowchart.min.js}"></script>
<script th:src="@{/editormd/lib/jquery.flowchart.min.js}"></script>
<script th:src="@{/editormd/editormd.js}"></script>
​
<script type="text/javascript">
    var testEditor;
    $(function () {
        // 绑定我们要渲染页面的 div
        testEditor = editormd.markdownToHTML("doc-content", {//注意:这里是上面DIV的id
            htmlDecode: "style,script,iframe",
            emoji: true,
            taskList: true,
            tocm: true,
            tex: true, // 默认不解析
            flowChart: true, // 默认不解析
            sequenceDiagram: true, // 默认不解析
            codeFold: true
        });
    });
</script>
</body>
</html>

9、最后别忘了编写保存文章和显示文章的Controller请求方法。

博客文章写作过程中,一直再寻找一个合适的编辑器。先后尝试了wangEditor、layui-Editor在用户页面得到应用。但文章的整洁程度难以和markdown媲美。mdendtor是个不错的选择,在安装完Django-enditor之后,最大的难题就是前端显示了。最初引入python库markdown,转化效果不是很理想。紧接着找到前端js对应的showdown.js库,显示效果依旧不好。于是,想到后台的预览窗口是怎么显示,直接把mdeditor的js抄到前端就行了。

后端适配

安装django-mdeditor

pip install django-mdeditor

添加app到sittings

INSTALLED_APPS = [
 'django.contrib.admin',
 'django.contrib.auth',
 ......
 'django.contrib.sitemaps',
 'mdeditor', # mdeditor编辑器
]

修改model

from mdeditor import fields as md_models

class Article(models.Model):
 id = models.AutoField(primary_key=True, max_length=32)
 ......
 content = md_models.MDTextField(verbose_name='正文', blank=False)
 ......

此时,刷新后端就显示正常了

前端适配

找到需要的js和css

在site-packages目录下找到如下js和css

mdeditor\static\mdeditor\js\lib\marked.min.js
mdeditor\static\mdeditor\js\editormd.js
mdeditor\static\mdeditor\css\editormd.preview.css

找到之后放到static目录下并在相应页面引入

前端适配

css和js处理

<!--引入样式文件-->
<link rel="stylesheet" href="/static/editor.md-master/css/editormd.preview.css"/>

<!--引入js文件-->
<script src="/static/editor.md-master/lib/marked.min.js"></script>
<script src="/static/editor.md-master/editormd.js"></script>

<!--处理逻辑-->
<script>
editormd.markdownToHTML("article_content", { //article_content是html文档的ID
emoji: true,
taskList: true,
});
</script>

html的处理

需要注意的是:style里面所有的内容不能少,否则造成样式会扭曲。textarea标签不能缺少,不然会造成代码的不识别。

<div id="article_content"
 style="-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;">
 <textarea style="display:none">{{ article.content | safe}}</textarea>
 </div>

后续注意

这样还不够,原作者这个markdownToHTML的方法并未考虑兼容原有纯HTML的文章。这样会造成我们非MD格式的文章样式上出现扭曲。此时可以打开editormd.js这个文件,搜索editormd.markdownToHTML方法。

在 var markdownDoc = (settings.markdown === "") ? saveTo.val() : settings.markdown;代码的下一行添加

if(markdownDoc.startsWith('<') || markdownDoc.endsWith('>')){
 $("#" + id).html(markdownDoc)
 return
 }

这样解决下来并不是很完美,最好判断下这个文章是不是一个XML文档比较稳妥,技术有限不能解决。留给你解决

译自: https://opensource.com/article/18/8/markdown-html-publishing

作者: Peter Cheer

译者: geekpi

用这个有用工具从 Markdown 文件创建一个基础的网站。

有很多理由喜欢 Markdown,这是一门简单的语言,有易于学习的语法,它可以与任何文本编辑器一起使用。使用像 Pandoc 这样的工具,你可以将 Markdown 文本转换为 各种流行格式 ,包括 HTML。你还可以在 Web 服务器中自动执行转换过程。由 TimoDörr 创建的名为 MDwiki 的 HTML5 和 JavaScript 应用可以将一堆 Markdown 文件在浏览器请求它们时转换为网站。MDwiki 网站包含一个操作指南和其他信息可帮助你入门:


Mdwiki 网站的样子。



在 Web 服务器内部,基本的 MDwiki 站点如下所示:


该站点的 web 服务器文件夹的样子



我将此项目的 MDwiki HTML 文件重命名为 START.HTML。还有一个处理导航的 Markdown 文件和一个 JSON 文件来保存一些配置设置。其他的都是网站内容。

虽然整个网站设计被 MDwiki 固定了,但内容、样式和页面数量却没有。你可以在 MDwiki 站点 查看由 MDwiki 生成的一系列不同站点。公平地说,MDwiki 网站缺乏网页设计师可以实现的视觉吸引力 —— 但它们是功能性的,用户应该平衡其简单的外观与创建和编辑它们的速度和简易性。

Markdown 有不同的风格,可以针对不同的特定目的扩展稳定的核心功能。MDwiki 使用 GitHub 风格 Markdown ,它为流行的编程语言添加了格式化代码块和语法高亮等功能,使其非常适合生成程序文档和教程。

MDwiki 还支持 “gimmick”,它增加了如嵌入 YouTube 视频和显示数学公式等额外功能。如果在某些项目中需要它们,这些值得探索。我发现 MDwiki 是创建技术文档和教育资源的理想工具。我还发现了一些可能不会立即显现出来的技巧和 hack。

当部署在 Web 服务器中时,MDwiki 可与任何现代 Web 浏览器一起使用。但是,如果你使用 Mozilla Firefox 访问 MDwiki,那么就不需要 Web 服务器。大多数 MDwiki 用户会选择在 Web 服务器上部署完整的项目,以避免排除潜在用户,但只需使用文本编辑器和 Firefox 即可完成开发和测试。任何现代浏览器都可以读取加载到 Moodle 虚拟学习环境(VLE)中的完整的 MDwiki 项目,这在教育环境中非常有用。 (对于其他 VLE 软件,这可能也是如此,但你应该测试它。)

MDwiki 的默认配色方案并非适用于所有项目,但你可以将其替换为从 Bootswatch.com 下载的其他主题。为此,只需在编辑器中打开 MDwiki HTML 文件,找到 extlib/css/bootstrap-3.0.0.min.css,然后插入下载的 Bootswatch 主题。还有一个 MDwiki gimmick,让用户在浏览器中载入 MDwiki 后,选择 Bootswatch 主题来替换默认值。我经常与有视力障碍的用户一起工作,他们倾向于喜欢高对比度的主题,在深色背景上使用白色文字。


MDwiki 页面使用 Bootswatch Superhero 主题



MDwiki、Markdown 文件和静态图像可以用于许多目的。但是,你有时可能希望包含 JavaScript 幻灯片或反馈表单。Markdown 文件可以包含 HTML 代码,但将 Markdown 与 HTML 混合会让人感到困惑。一种解决方案是在单独的 HTML 文件中创建所需的功能,并将其显示在带有 iframe 标记的 Markdown 文件中。我从 Twine Cookbook 知道了这个想法,它是 Twine 交互式小说引擎的支持站点。Twine Cookbook 实际上并没有使用 MDwiki,但结合 Markdown 和 iframe 标签开辟了广泛的创作可能性。

这是一个例子:

此 HTML 将显示由 Markdown 文件中的 Twine 交互式小说引擎创建的 HTML 页面。

<iframe height="400" src="sugarcube_dungeonmoving_example.html" width="90%"></iframe>

MDwiki 生成的站点结果如下所示:



简而言之,MDwiki 是一个出色的小应用,可以很好地实现其目的。


via: https://opensource.com/article/18/8/markdown-html-publishing

作者: Peter Cheer 选题: lujun9972 译者: geekpi 校对: wxy

本文由 LCTT 原创编译, Linux中国 荣誉推出

点击“了解更多”可访问文内链接