Parsing Markdown with Vue v2

I am trying to find a simple way of parsing Markdown-strings in Vue, but have looped around a few times getting confused by various examples using filters, computed properties, and alike methods.

I am following what appears to definitely be a Vue v2 example: Markdown Editor Example. Using a Starter Template, I have a custom component called Works, defined in works.js like so:

import Vue from 'vue';
import template from './works.html';
var marked = require('marked');

export default Vue.extend({
  template,
  props: ['data'],
  filters: {
    compiledMarkdown: function(input) {
      return marked(input);
    }
  }
});

And following the Syntax-Guide on Filters I tried to apply it to a string like this: {{ item.description | compiledMarkdown }}. The string in question contains some bogus including simple Markdown:

description: 'Lorem **ipsum** dolor sit amet, consectetur adipiscing elit.  Quisque fringilla purus maximus nibh laoreet luctus nec et orci. Proin id dui quis nulla rutrum dignissim non at *magna*.'

However, this returns pure HTML:

<p>Lorem <strong>ipsum</strong> dolor sit amet, consectetur adipiscing elit.  Quisque fringilla purus maximus nibh laoreet luctus nec et orci. Proin id dui quis nulla rutrum dignissim non at <em>magna</em>.</p>

Seemingly, the solution would be to use the special v-html-attribute: <div v-html="item.description | compiledMarkdown "></div>, but this just returns 0 and yields a Property or method "compiledMarkdown" is not defined on the instance but referenced during render.

How can I use the Markdown-filter to return the string as actual HTML?

And further, is it possible to make the filter globally available to all components?

  1. Filters only work in {{}} Interpolations and in Attribute bindings (The lauter since 2.1). So theis dont work with v-html (which is a directive), which is why the example you linked to uses as computed property.

As I understand it, from reading the docs and looking at examples, a computed property only works on the specific property within the specific component, ie. this.input in the Markdown Editor.

Since this is a case of general app-wide text-formatting, I assume a filter is most apt:

Use filters primarily for simple text formatting that needs to be reused all across your app. Filters should be pure - no side effects, just data in and data out. - Evan

Can the computed-method be used as a global function for parsing content?

After a bit more testing, I found that in the component I can add a method that works:

  methods: {
    marked: function(input) {
      return marked(input);
    }
  }

But could this be elevated to a global method by using a mixin or plugin?

1 Like

Ok, finally a solution. Use a mixin, not a filter or component-method, like so:

var marked = require('marked');
Vue.mixin({
  methods: {
    marked: function(input) {
      return marked(input);
    }
  }
});

Then Markdown can be parsed using the v-html-directive like this: <span v-html="marked(item.description)"></span>, in any component.

1 Like

Really great find OleVik, I was able to implement this solution super easy. Have you found a way to format the markdown if it is code?

for example this is what I am currently seeing:

EDIT: actually it looks like there are options you can use that might be able to solve this. Going to give it a try.