富文本編輯器Editormd的配置使用

我們經常可以看到各個博客網站中用於編輯文章的富文本編輯器,在富文本編輯器中,我們可以對我們的編輯內容樣式進行設置。富文本編輯器一般是通過插件來實現的,我們只需要在頁面中配置一下插件提供的一些API即可。本例中使用Editormd來演示如何配置使用富文本編輯器。

Editormd簡介

Editormd是國內開源的一款在線Markdown編輯器,可嵌入的 Markdown 在線編輯器(組件),基於 CodeMirror、jQuery 和 Marked 構建。

主要特性

支持“標準”Markdown / CommonMark和Github風格的語法,也可變身爲代碼編輯器。

  • 支持實時預覽、圖片(跨域)上傳、預格式文本/代碼/表格插入、代碼摺疊、搜索替換、只讀模式、自定義樣式主題和多語言語法高亮等功能。
  • 支持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/
Editormd官網

創建文章表

在使用富文本編輯器之前,先來創建一個文章表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靜態資源,靜態資源的目錄結構如下圖所示。
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請求方法。

//獲取文章進行顯示
@GetMapping("/{id}")
public String show(@PathVariable("id") int id,Model model){
  Article article = articleMapper.getArticleById(id);
  model.addAttribute("article",article);
  return "article";
}

// 保存文章到數據庫!
@PostMapping("/addArticle")
public String addArticle(Article article){
  articleMapper.addArticle(article);
  return "editor";
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章