DEV Community

Cover image for Making a Markdown Editor for Your Vue Blog with Front Matter Support
James Sinkala
James Sinkala

Posted on • Edited on • Originally published at jamesinkala.com

Making a Markdown Editor for Your Vue Blog with Front Matter Support

Markdown is a plain text format for writing structured documents, based on formatting conventions from email and usenet. On the other hand, front matter in the article's context is simply YAML's front matter block which I can assume, was inspired by the same word as used in book design.
Example from the following block,

---
title: Outline title
description: The shortest description ever written.
---
Enter fullscreen mode Exit fullscreen mode

we can obtain the following object:

{
  title: 'Outline title',
  description: 'The shortest description ever written'
}
Enter fullscreen mode Exit fullscreen mode

We'll be using the front-matter npm module to achieve this.

The inspiration for this tutorial is DEV.to's basic markdown editor that pushed me to create one for my own website.
Using front matter in the editor is a sound concept since it is better to have all article meta-data such as title, tags, description etc within the article content area than having a form with several input fields.

Creating The Editor

What we want is for our editor to take the combination of front-matter data and markup, then be able to extract the two before storing that data separately somewhere. We'll be using the front-matter module to extract the data we need from the text editor content.

Here is the editor in action.
Alt Text

Since we'll be working with markdown and front-matter in our editor, we'll add the two npm modules first.

$ npm i front-matter marked
Enter fullscreen mode Exit fullscreen mode

Note: marked provides the following warning "Marked does not sanitize the output HTML. Please use a sanitize library, like DOMPurify (recommended), sanitize-html or insane on the output HTML!"

UIKit's css framework has been used to create the template for the editor as you'll notice from the CSS classes but feel free to style the editor to your liking.

The Template

<div id="editor-form-container" class="uk-margin">
  <div id="button-container">
    <button @click.prevent="previewMarkdown = !previewMarkdown" class="uk-button uk-button-primary uk-float-left">{{previewMarkdown ? "Edit Article" : "Preview Article"}}</button>
  </div>
  <div id="editor-container">
    <textarea v-if="!previewMarkdown" id="d1" v-model="allContent" class="uk-textarea editor"></textarea>
    <div v-else class="preview" v-html="compiledMarkdown"></div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

The Javascript

import Marked from 'marked'
import FrontMatter from 'front-matter'
export default {
  name: "MarkdownEditor", 
 ...
Enter fullscreen mode Exit fullscreen mode

Our Variables

  ...
  data(){
    return {
      previewMarkdown: false,
      startContent: `---
title: 
short_description: 
tags: 
post_image: 
publish: false
---
Write content here
`,
      allContent:"",
      articleData: "",
    },
  },
  ...
Enter fullscreen mode Exit fullscreen mode

previewMarkdown: A bool value that toggles the text of our button showing when we are editing or previewing the article.
startContent: What the text editor contains when the text editor is mounted.
allContent: All of the contents of the text editor at a given time.

  ...
  computed:{
    compiledMarkdown(){
      let data = FrontMatter(this.allContent)
      return Marked(data.body)
    },
  },
  ...
Enter fullscreen mode Exit fullscreen mode

The compiledMarkdown computed value returns the processed html from the markdown within allContent which we preview within the block with v-html on the template above.

When the component has been mounted we assign the startContent to the allContent variable.

  ...
  mounted(){
    this.allContent = this.startContent
  },
  ...
Enter fullscreen mode Exit fullscreen mode

With the above code we can edit and preview our article. To get the variables passed in the front-matter block we'll add a getVariables() function and call it when needed.

  ...
  methods: {
    getVariables(){
      const {body, attributes} = FrontMatter(this.allContent)
      $nextTick(()=>{
        articleData = {
          content: body,
          title: attributes.title,
          description: attributes.short_description,
          tags: attributes.tags,
          image: attributes.post_image,
          publish: attributes.publish,
        }
      })
      // Then proceed to using articleData object as needed
    }
  },
  ...
Enter fullscreen mode Exit fullscreen mode

This is just a starting point to this markdown editor. More features can be added to it such as text persistence with the help of vuex and the vuex-persistedstate plugin and more.

Top comments (0)