聊聊富文本編輯器
簡介
思考:我們平時在博客園,或者CSDN等平台進行寫作的時候,有同學思考過他們的編輯器是怎么實現的嗎?
在博客園后台的選項設置中,可以看到一個文本編輯器的選項:
其實這個就是富文本編輯器,市面上有許多非常成熟的富文本編輯器,比如:
-
Editor.md——功能非常豐富的編輯器,左端編輯,右端預覽,非常方便,完全免費
-
wangEditor——基於javascript和css開發的 Web富文本編輯器, 輕量、簡潔、界面美觀、易用、開源免費。
-
TinyMCE——TinyMCE是一個輕量級的基於瀏覽器的所見即所得編輯器,由JavaScript寫成。它對IE6+和Firefox1.5+都有着非常良好的支持。功能齊全,界面美觀,就是文檔是英文的,對開發人員英文水平有一定要求。
-
百度ueditor——UEditor是由百度web前端研發部開發所見即所得富文本web編輯器,具有輕量,功能齊全,可定制,注重用戶體驗等特點,開源基於MIT協議,允許自由使用和修改代碼,缺點是已經沒有更新了
-
kindeditor——界面經典。
-
Textbox——Textbox是一款極簡但功能強大的在線文本編輯器,支持桌面設備和移動設備。主要功能包含內置的圖像處理和存儲、文件拖放、拼寫檢查和自動更正。此外,該工具還實現了屏幕閱讀器等輔助技術,並符合WAI-ARIA可訪問性標准。
-
CKEditor——國外的,界面美觀。
-
quill——功能強大,還可以編輯公式等
-
simditor——界面美觀,功能較全。
-
summernote——UI好看,精美
-
jodit——功能齊全
-
froala Editor——界面非常好看,功能非常強大,非常好用(非免費)
總之,目前可用的富文本編輯器有很多......這只是其中的一部分
Editor.md
我這里使用的就是Editor.md,作為一個資深碼農,Mardown必然是我們程序猿最喜歡的格式,看下面,就愛上了!
我們可以在官網下載它:https://pandao.github.io/editor.md/ , 得到它的壓縮包!
解壓以后,在examples目錄下面,可以看到他的很多案例使用!學習,其實就是看人家怎么寫的,然后進行模仿就好了!
我們可以將整個解壓的文件倒入我們的項目,將一些無用的測試和案例刪掉即可!
基礎工程搭建
數據庫設計
article:文章表
建表SQL:
CREATE TABLE `article` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'int文章的唯一ID',
`author` varchar(50) NOT NULL COMMENT '作者',
`title` varchar(100) NOT NULL COMMENT '標題',
`content` longtext NOT NULL COMMENT '文章的內容',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
基礎項目搭建
1、建一個SpringBoot項目配置
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
2、實體類:
//文章類
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Article implements Serializable {
private int id; //文章的唯一ID
private String author; //作者名
private String title; //標題
private String content; //文章的內容
}
3、mapper接口:
@Mapper
@Repository
public interface ArticleMapper {
//查詢所有的文章
List<Article> queryArticles();
//新增一個文章
int addArticle(Article article);
//根據文章id查詢文章
Article getArticleById(int id);
//根據文章id刪除文章
int deleteArticleById(int id);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kuang.mapper.ArticleMapper">
<select id="queryArticles" resultType="Article">
select * from article
</select>
<select id="getArticleById" resultType="Article">
select * from article where id = #{id}
</select>
<insert id="addArticle" parameterType="Article">
insert into article (author,title,content) values (#{author},#{title},#{content});
</insert>
<delete id="deleteArticleById" parameterType="int">
delete from article where id = #{id}
</delete>
</mapper>
既然已經提供了 myBatis 的映射配置文件,自然要告訴 spring boot 這些文件的位置
mybatis:
mapper-locations: classpath:com/kuang/mapper/*.xml
type-aliases-package: com.kuang.pojo
編寫一個Controller測試下,是否ok;
文章編輯整合(重點)
1、導入 editor.md 資源 ,刪除多余文件
2、編輯文章頁面 editor.html、需要引入 jQuery;
<!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>
<div id="article-content">
<textarea name="content" id="content" style="display:none;"></textarea>
</div>
</form>
</div>
</div>
</div>
</body>
<!--editormd-->
<script th:src="@{/editormd/lib/jquery.min.js}"></script>
<script th:src="@{/editormd/editormd.js}"></script>
<script type="text/javascript">
var testEditor;
//window.onload = function(){ }
$(function() {
testEditor = editormd("article-content", {
width : "95%",
height : 400,
syncScrolling : "single",
path : "../editormd/lib/",
saveHTMLToTextarea : true, // 保存 HTML 到 Textarea
emoji: true,
theme: "dark",//工具欄主題
previewTheme: "dark",//預覽主題
editorTheme: "pastel-on-dark",//編輯主題
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"]
},
/*自定義功能按鈕,下面我自定義了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>
</html>
3、編寫Controller,進行跳轉,以及保存文章
@Controller
@RequestMapping("/article")
public class ArticleController {
@GetMapping("/toEditor")
public String toEditor(){
return "editor";
}
@PostMapping("/addArticle")
public String addArticle(Article article){
articleMapper.addArticle(article);
return "editor";
}
}
圖片上傳問題
1、前端js中添加配置
//圖片上傳
imageUpload : true,
imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"],
imageUploadURL : "/article/file/upload", // //這個是上傳圖片時的訪問地址
2、后端請求,接收保存這個圖片, 需要導入 FastJson 的依賴!
//博客圖片上傳問題
@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("-", "");
//通過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;
}
3、解決文件回顯顯示的問題,設置虛擬目錄映射!在我們自己拓展的MvcConfig中進行配置即可!
@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/");
}
}
表情包問題
自己手動下載,emoji 表情包,放到圖片路徑下:/editormd/plugins/emoji-dialog/emoji/
表情包下載地址:https://github.com/SemiWarm/SemiWarmAdminPhotos/blob/master/emoji.zip
修改editormd.js文件
// Emoji graphics files url path
editormd.emoji = {
path : "../editormd/plugins/emoji-dialog/emoji/",
ext : ".png"
};
文章展示
1、Controller 中增加方法
@GetMapping("/{id}")
public String show(@PathVariable("id") int id,Model model){
Article article = articleMapper.getArticleById(id);
model.addAttribute("article",article);
return "article";
}
2、編寫頁面 article.html
<!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>
<link rel="stylesheet" th:href="@{/editormd/css/editormd.preview.css}" />
<script th:src="@{/editormd/lib/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 () {
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>
重啟項目,訪問進行測試!大功告成!
小結:
有了富文本編輯器,我們網站的功能就會又多一項,大家到了這里完全可以有時間寫一個屬於自己的博客網站了,根據所學的知識是完全沒有任何問題的!
寫在最后
其實本功能所依賴的文件只有這么多,不用全部導入進項目,影響服務器的運行效率,和項目承載的壓力!