nuxt-modules / mdc

MDC supercharges regular Markdown to write documents interacting deeply with any Vue component.
MIT License
181 stars 21 forks source link

MDCSlot not rendering markdown when unwrapping #251

Open Jesus82 opened 2 weeks ago

Jesus82 commented 2 weeks ago

I have a simple component in order to render markdown that I get from an API. I want to be able to render it without a wrapping

, so I'm using MDCSlot. Here's my custom MDRenderer component.


<template>
  <MDCSlot unwrap="p" />
</template>

<script setup></script>

And I'm using it like this, but MD is not being rendered. (check working example here)

<template>
    <MDRenderer>{{ md }}</MDRenderer>
</template>

<script setup>
const md = `---
title: Sam
---
`
</script>
robinkloeckner commented 2 weeks ago

I have been using <MDCSlot> component only in global components which are addressed within the Markdown - similar to the example in the documentation. However, if you want to render Markdown from an API to a child component while unwrapping <p>, you could do the following:

app.vue

<template>
  <MDRenderer>
    <MDC :value="md" unwrap="p" />
  </MDRenderer>
</template>

<script setup>
  const md = `
  # H1

  paragraph
  `
</script>

<style>
// Just for illustration purposes
h1, p {
  color: red;
}
</style>

MDRender.vue

<template>
 <slot />
</template>

In the <MDRenderer> your are taking the standard <slot> component. In app.vue or any parent component, instead of passing a Markdown string you are passing <MDC>. The component parses and renders the string as referenced in the :value attribute and unwraps all tags as defined in unwrap.

Jesus82 commented 2 weeks ago

Thanks for the detailed answer. Finally what I did based on your code, in order to have a "single component" is the following. Could be nice that there is something native to fit this case, though.

<template>
  <MDRenderer 
     :md="md"
     tag="h2"
     class="text-red" 
  />
</template>

<script setup>
const md = `---
title: Sam
---
`
</script>

<style scoped>
.text-red {
    color: red
}
</style>

MDRenderer.vue

<template>
  <MDRendererSlot>
    <MDC
      :value="props.md"
      unwrap="p"
      :tag="props.tag"
      :class="props.class"
    />
  </MDRendererSlot>
</template>

<script setup>
const props = defineProps({
  tag: {
    type: String,
    default: 'p',
  },
  class: {
    type: String,
    default: '',
  },
  md: {
    type: String,
    required: true,
  },
})
</script>

MDRendererSlot.vue

<template>
  <slot />
</template>

<script setup>
</script>