preface

I was building a personal blog site, and I needed a Markdown editor for my blog, and I looked at some of the tutorials online, and I decided to use Simplemde and I thought it would be pretty straightforward to use, but when I put it into practice, I found that there were some things that I needed to improve on, like uploading pictures that were a pain in the ass

The final result

  1. Markdown grammar
  2. Real-time preview
  3. Upload the image to the server
  4. Finally generate HTML

Installation and initialization

npm install simplemde --save

Add a textarea to HTML

Add simplemde instantiation in Vue’s life-cycle function Mounted

var simplemde = new SimpleMDE({
      el: document.getElementById(simplemde)
    })
Copy the code

El specifies the Textarea element created for us through the DOM and, if omitted, automatically grabs the first Textarea in the HTML structure

Bind events so that our content data is always in sync with the typed data simplemde gets

simplemde.codemirror.on("change", () => {
      this.content = simplemde.value()
    })
Copy the code

To upload pictures

In the original Simplemde, clicking the picture button would look something like this

No way, since there is no have to make their own

First we create a hidden input

<input style="display:none" accept="image/gif,image/jpeg,image/jpg,image/png" type="file" id="upInput" ref="upInput">
Copy the code

I’m going to accept a file as an image and I’m going to click on it and it’s going to pop up and I’m going to hide that local upload file because we don’t want that button and we’re going to click on simplemde’s Image button to upload it which isn’t very useful, but it’s nice

So we’re just going to hide this input, just use its click method so that clicking on the image button is the same thing as clicking on this input in simplemde’s source code, go to the function that the image button calls and comment out the original one and add this

So once we’ve selected the image, in order to preview it in real time we want to send it to the back end and store it in the front end using Axios plus FormData

var input = this.$refs.upInput
var formData = new FormData()
formData.append("i", input.files[0])
var config = {
     headers: {
       "Content-Type": "multipart/form-data"
      }
   }
this.$axios.post("/data/myupload", formData, config)
Copy the code

On the back end, I’m using node, which uses the Multer module to receive data in mulipart/form-data format

Var storage = multer.diskStorage({// storage path destination: function (req, file, cb) { cb(null, '.. /static/upload/')}, // store filename filename: Function (req, file, cb) {cb(null, '${date.now ()}-${file.originalname}')}}) Router. post('/data/myupload', upload.single(' I '), function (req, res, Next) {// Send the saved filename back to the front-end res.send(req.file.filename)});Copy the code

So when the front end receives the file name, it wraps it up with the storage path and writes it into a text box which is the string of characters that you see when you click on the image button before and then previews it

this.$axios.post("/data/myupload", formData, config).then((res)=> { var urlname=`! [](/static/upload/${res.data})` simplemde.value(`${this.content}\n${urlname}\n`) })Copy the code

It looks like everything’s all right but there’s one thing missing

The input click() itself is not asynchronous, but it takes time for you to select the image, and all subsequent code (even asynchronous code) executes during this process, meaning that all of the sending stores that are being written are executed before the image is selected

In order to execute after selecting the image, we add a new listener event, listen for the input change, and throw all the previous code into it

var input = this.$refs.upInput input.addEventListener("change", () => { var formData = new FormData() formData.append("i", input.files[0]) var config = { headers: { "Content-Type": "multipart/form-data" } } this.$axios.post("/data/myupload", formData, config).then((res)=> { var urlname=`! [](/static/upload/${res.data})` simplemde.value(`${this.content}\n${urlname}\n`) }) })Copy the code

This will achieve our image upload effect

According to

So for example, with the editor, we write a blog post, we store it in the background and we want to pull it up in some other component which is a string to HTML

Simply call Simplemde’s prototype chain method

this.contentMarkdown = SimpleMDE.prototype.markdown(content)
Copy the code

Then put the data into V-HTML

<div v-html="contentMarkdown"></div>
Copy the code

You can show

Let’s see the final result again

PS

This article is to save the image in the server’s project directory, in fact, you can upload the image to the map bed and some additional functions, such as drag and drop images directly, or paste. When I have time to work on it later on