Editor.md – very rich function Editor, left side edit, right side preview, very convenient, completely free

  • Website: pandao. Making. IO/editor/md
  • Download website: pandao. Dead simple.. IO/editor/md

Foundation engineering construction

Database design

Article: a list of articles

field note
id int The unique ID of the article
author varchar The author
title varchar The title
content longtext The content of the article

Build table SQL:

CREATE TABLE 'article' (' id 'int (10) NOT NULL AUTO_INCREMENT COMMENT 'int ', 'author' varchar(50) NOT NULL COMMENT '主 ',' title 'varchar(100) NOT NULL COMMENT' 主 ', 'content' longtext NOT NULL COMMENT '表 示 ', PRIMARY KEY (' id')) ENGINE=InnoDB DEFAULT CHARSET=utf8Copy the code

Foundation project construction

1. Create a SpringBoot project configuration

spring:
datasource:
  username: root
  password: 123456
#? ServerTimezone =UTC Resolve time zone errors
  url: jdbc:mysql://localhost:3306/springboot? serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
  driver-class-name: com.mysql.cj.jdbc.Driver
Copy the code
<resources>
   <resource>
       <directory>src/main/java</directory>
       <includes>
           <include>**/*.xml</include>
       </includes>
       <filtering>true</filtering>
   </resource>
</resources>
Copy the code

2. Entity class

/ / class
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Article implements Serializable {

   private int id; // The unique ID of the article
   private String author; / / the author name
   private String title; / / title
   private String content; // The content of the article
}
Copy the code

3. Mapper interface

@Mapper
@Repository
public interface ArticleMapper {
   // Query all articles
   List<Article> queryArticles(a);

   // Add a new article
   int addArticle(Article article);

   // Query articles based on their id
   Article getArticleById(int id);

   // Delete articles according to their id
   int deleteArticleById(int id);

}
Copy the code

      
<! DOCTYPEmapper 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>
Copy the code

Now that you have provided myBatis mapping configuration files, it is natural to tell Spring Boot where these files are located

mybatis:
mapper-locations: classpath:com/kuang/mapper/*.xml
type-aliases-package: com.kuang.pojo
Copy the code

Write a Controller test, ok;

Article editing and Integration (emphasis)

1. Import the editor.md resource and delete unnecessary files

2, Edit the article page editor. HTML, need to introduce jQuery;

<! DOCTYPEhtml>
<html class="x-admin-sm" lang="zh" xmlns:th="http://www.thymeleaf.org">

<head>
   <meta charset="UTF-8">
   <title>Qin jiang '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, the initial - scale = 0.8, the 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">
           <! -- Blog Form -->
           <form name="mdEditorForm">
               <div>Title:<input type="text" name="title">
               </div>
               <div>The author:<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%"./ / wide
           height : 600./ / high
           syncScrolling : "single".path : ".. /editormd/lib/".// Load the editor lib path
           saveHTMLToTextarea : true.// Save HTML to Textarea
           emoji: true.// Enable emoticons
           theme: "dark".// Toolbar theme
           previewTheme: "dark".// Preview the theme
           editorTheme: "pastel-on-dark".// Edit the theme
           tex : true.// Enable scientific formula TeX language support, default off
           flowChart : true.// Enable flowchart support, disabled by default
           sequenceDiagram : true.// Enable sequence/sequence diagram support, default off,
           // Image upload
           imageUpload : true.imageFormats : ["jpg"."jpeg"."gif"."png"."bmp"."webp"].imageUploadURL : "/article/file/upload".onload : function() {
               console.log('onload'.this);
          },
           /* Specifies the function button to display */
           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"]},/* Custom function button, below I customize 2, one is to publish, one is to return to home page */
           toolbarIconTexts : {
               releaseIcon : " ".index : ",},/* Specifies the callback function */ for the custom button
           toolbarHandlers: {releaseIcon : function(cm, icon, cursor, selection) {
                   // Form submission
                   mdEditorForm.method = "post";
                   mdEditorForm.action = "/article/addArticle";// The path to the server
                   mdEditorForm.submit();
              },
               index : function(){
                   window.location.href = '/'; }}}); });</script>

</html>
Copy the code

Write Controller, jump, and save the article

@Controller
@RequestMapping("/article")
public class ArticleController {

   @GetMapping("/toEditor")
   public String toEditor(a){
       return "editor";
  }
   
   @PostMapping("/addArticle")
   public String addArticle(Article article){
       articleMapper.addArticle(article);
       return "editor"; }}Copy the code

Image uploading problem

1. Add configuration to front-end JS

// Image upload
imageUpload : true.imageFormats : ["jpg"."jpeg"."gif"."png"."bmp"."webp"].imageUploadURL : "/article/file/upload".// // this is the address to access when uploading pictures
Copy the code

2, the backend request, receive to save the image, need to import the FastJson dependency

// Blog image uploading problem
@RequestMapping("/file/upload")
@ResponseBody
public JSONObject fileUpload(@RequestParam(value = "editormd-image-file", required = true) MultipartFile file, HttpServletRequest request) throws IOException {
   // Upload path save Settings

   // Get the current SpringBoot project path: system.getProperty ("user.dir")
   String path = System.getProperty("user.dir") +"/upload/";

   // Sort by month:
   Calendar instance = Calendar.getInstance();
   String month = (instance.get(Calendar.MONTH) + 1) +"Month";
   path = path+month;

   File realPath = new File(path);
   if(! realPath.exists()){ realPath.mkdir(); }// Upload file address
   System.out.println("Upload file save address:"+realPath);

   // Solve the file name problem: we use uuid;
   String filename = "ks-"+UUID.randomUUID().toString().replaceAll("-"."");
   // Write the file directly via CommonsMultipartFile (note this time)
   file.transferTo(new File(realPath +"/"+ filename));

   // Call back to editorMD
   JSONObject res = new JSONObject();
   res.put("url"."/upload/"+month+"/"+ filename);
   res.put("success".1);
   res.put("message"."upload success!");

   return res;
}
Copy the code

3, solve the problem of file display, set up virtual directory mapping! In our own extended MvcConfig configuration can be!

@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

   // Save the file to the real directory /upload/.
   PNG file name = 1. PNG file name = 1. PNG file name = 1.
   @Override
   public void addResourceHandlers(ResourceHandlerRegistry registry) {
       registry.addResourceHandler("/upload/**")
          .addResourceLocations("file:"+System.getProperty("user.dir") +"/upload/"); }}Copy the code

The Emoji problem

Manually download the emoji package and place it in the picture path:

Modify the editormd.js file

// Emoji graphics files url path
editormd.emoji     = {
   path : ".. /editormd/plugins/emoji-dialog/emoji/".ext   : ".png"
};
Copy the code

The article shows

1. Add methods to Controller

@GetMapping("/{id}")
public String show(@PathVariable("id") int id,Model model){
   Article article = articleMapper.getArticleById(id);
   model.addAttribute("article",article);
   return "article";
}
Copy the code

2. Write the article. HTML page

<! DOCTYPEhtml>
<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>
   <! -- Article headers: title, author, last updated date, navigation -->
   <h2 style="margin: auto 0" th:text="${article.title}"></h2>The author:<span style="float: left" th:text="${article.author}"></span>
   <! -- Text body content -->
   <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", {// Note that this is the id of the DIV above
           htmlDecode: "style,script,iframe".emoji: true.taskList: true.tocm: true.tex: true.// No parsing by default
           flowChart: true.// No parsing by default
           sequenceDiagram: true.// No parsing by default
           codeFold: true}); });</script>
</body>
</html>
Copy the code

Restart the project and visit for testing! And you’re done!