Search code examples
vue.jsnuxt.jsnuxt-content

Use nuxt/content to display markdown fetched from a database


I'm using nuxt / content in my app and it's working fine. In another part of the app, I'd like to fetch some markdown from a database and display it.

let mytext = "Some *markdown* fetched from a db here."

<nuxt-content :document="mytext" />

This does not work because I'm missing a parsing step; when you do $content("a_page_title_here").fetch() it parses the fetched text and presents it to the component as structured json.

How do I use $content to parse text, so it can be passed to the component for display?

I'll bet there is a way to do it, but the documentation does not include a reference section that describes everything you can do with $content.

If there is an easy way to use the underlying Remark component, I can do that.


Solution

  • nuxt@3 and @nuxt/content@2

    You can use @nuxt/content's Markdown transformer to parse an arbitrary string:

    // ~/utils/parseMarkdown.js
    import markdownParser from '@nuxt/content/transformers/markdown'
    
    // first arg to parse() is for id, which is unused
    export const parseMarkdown = md => markdownParser.parse('custom.md', md)
    

    Then render it with @nuxt/content's ContentRendererMarkdown component like this:

    <script setup>
    import { parseMarkdown } from '~/utils/parseMarkdown'
    
    const result = ref(null)
    const loadMarkdown = async () => {
      const data = await $fetch('https://example.com/page.md')
      result.value = await parseMarkdown(data)
    }
    loadMarkdown()
    </script>
    
    <template>
      <ContentRendererMarkdown :value="result" v-if="result" />
    </template>
    

    demo 1

    nuxt@2 and @nuxt/content@1

    You can use the underlying Markdown class from @nuxt/content. Its async toJSON() function takes a filename or string (via gray-matter) that contains Markdown to parse, and resolves a JSON object that could be passed to <nuxt-content>.document.

    To initialize Markdown with the default rehype plugins, use getDefaults() and processMarkdownOptions():

    // ~/utils/parseMarkdown.js
    import Markdown from '@nuxt/content/parsers/markdown'
    import { getDefaults, processMarkdownOptions } from '@nuxt/content/lib/utils'
    
    export async function parseMarkdown(md) {
      const options = getDefaults()
      processMarkdownOptions(options)
      return new Markdown(options.markdown).toJSON(md) // toJSON() is async
    }
    

    Then use it in your component like this:

    <script>
    import { parseMarkdown } from '~/utils/parseMarkdown'
    
    export default {
      async asyncData({ $axios }) {
        const resp = await $axios.get('https://example.com/page.md')
        const page = await parseMarkdown(resp.data)
        return { page }
      }
    }
    </script>
    
    <template>
      <nuxt-content :document="page" />
    </template>
    

    demo 2