wilcode
wilcode

Reputation: 625

Vue.js markdown filter

I'm using Evan You's example of how to convert HTML to markdown - https://jsfiddle.net/yyx990803/oe7axeab/.

Installing the marked package through npm and then implementing this leads to the error, 'marked' is not defined.

If I include the cdn link in my index.html file, the markdown is then converted to "0" and I get the error:

[Vue warn]: Property or method "marked" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

EDIT:

I tried to include it in my main.js as follows:

import App from './App.vue';
import router from './router';
import store from './store';

import './css/main.css';
import i18n from './i18n';
import marked from 'marked';

const debugSetting = window.ApplicationConfig.DEBUG;
Vue.config.debug = debugSetting;

Vue.config.productionTip = false;

new Vue({
    router,
    store,
    i18n,
    marked,

    render: function(h) {
        return h(App);
    },
}).$mount('#app');

This doesn't feel right though, hence why I tried with the cdn just to see if that at least worked.

component

<template>
    <main-layout>
        <div class="wrapper" v-html="terms | marked"></div>
    </main-layout>
</template>

<script>
import MainLayout from '@/layouts/Main.vue';

import { getTerms } from '../api';

export default {
    name: 'Terms',
    components: {
        MainLayout,
    },
    data() {
        return {
            terms,
        };
    },
    filters: {
        marked: marked,
    },
    async mounted() {
        try {
            const response = await getTerms();

            if (response) {
                this.terms = response.data;
                console.log(this.terms);
            }
        } catch (err) {
            console.log(err);
        }
    },
};
</script>

Upvotes: 4

Views: 4228

Answers (4)

TitanFighter
TitanFighter

Reputation: 5074

Example of how marked can be used globally.

main.js

import Vue from 'vue'
import App from './App.vue'

import router from './router'
import store from '@/store'

import marked from 'marked'

// Lets use the code below inside a components
// Vue.marked()
// this.$marked()
Vue.use({
  install () {
    Vue.marked = marked
    Vue.prototype.$marked = marked
  }
})

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

someFile.vue

<template>
    <div v-html="$marked(someMarkdownText)"></div>
</template>

export default {
    name: 'Terms',
    components: {},
    data () {
        return {
            someMarkdownText: '# hello',
        }
    },
    mounted () {}
}

Upvotes: 3

y_nk
y_nk

Reputation: 2275

The reason why is because filters are not meant to be used in a v-html directive. When doing so, marked is looked upon properties/methods of the component, which is, indeed, not declared (since it's a filter).

The only ways for you are to move marked to data() or methods{} or even better, build a computed property out of it (so it's cached).

It could have been possible if there was a {{{ }}} in the template engine, but as there's not, what you want to achieve is impossible.


PS: the example you mentioned is working because it's using Vue v1.0 ; only updating the dependencies would make that fiddle fail.

Upvotes: 1

wilcode
wilcode

Reputation: 625

I used the latest version of the example and this worked straight away.

https://jsfiddle.net/yyx990803/v368d4g3/

    compiledMarkdown: function () {
      return marked(this.input, { sanitize: true })
    }
  },

Upvotes: 1

haMzox
haMzox

Reputation: 2109

You are missing the marked import. Globally injecting it to main.js will not help!

<template>
    <main-layout>
        <div class="wrapper" v-html="terms | marked"></div>
    </main-layout>
</template>

<script>
...
import marked from 'marked';
...
</script>

Upvotes: 3

Related Questions