MDC Syntax

MDC stands for MarkDown Components. This syntax supercharges regular Markdown to write documents interacting deeply with any Vue component from your components/content/ directory or provided by a module.

Install the MDC VS Code extension to get proper syntax highlighting for your MDC components.

Block Components

Block components are components that accept Markdown content or another component as a slot.

Any component in the components/content/ directory or made available globally in your application can be used in Markdown files.

The component must contain either:

  • A <slot /> to accept raw text or another component.
  • The <ContentSlot /> component to accept formatted text.

In a markdown file, use the component with the :: identifier.

index.md
::cardThe content of the card::
Card.vue
<template>  <div class="p-6 border bg-white dark:bg-black dark:border-gray-700 rounded">    <slot />  </div></template>

The content of the card

Slots

A component's slots can accept content or another components.

  • The default slot renders the top-level content inside the block component.
  • named slots use the # identifier to render the corresponding content.
index.md
::heroDefault slot text#descriptionThis will be rendered inside the `description` slot.::
Hero.vue
<template>  <section>    <h1 class="text-4xl"><slot /></h1>    <slot name="description" />  </section></template>

Default slot text

This will be rendered inside the description slot.

Nesting

MDC supports nested components inside slots by indenting them.

index.md
::hero  :::card    A nested card    ::card      A super nested card    ::  :::::

A nested card

A super nested card

You can add more :::: when nesting components as a visual reminder.

Markdown rendering

The <ContentSlot /> component is auto-imported by Nuxt Content. It acts as a special slot that accepts rich text rendered by Markdown.

The unwrap prop accepts an HTML tag that will be used to unwrap the content, useful when using tags such as title tags (<h1>, <h2>, ...) or inline tags (<button>, <a>, ...).

TheTitle.vue
<template>  <h1 class="text-4xl">    <ContentSlot :use="$slots.default" unwrap="p" />  </h1></template>
index.md
::the-titleA [rich text](/) will be **rendered** by the component.::

A rich text will be rendered by the component.

The <ContentSlot /> component can act as a named slot with the use property:

<ContentSlot :use="$slots.description" unwrap="p">

Inline components

Inline components are components without slots or <ContentSlot />.

They can be used with the : identifier.

index.md
# Title:banner
Banner.vue
<template>  <aside>    This component does not have any children.  </aside></template>

If you want to use an inline component followed by specific characters like -, _ or :, you can use a dummy props specifier after it.

:hello{}-world

In this example, :hello{} will search for the <Hello /> component, and -world will be plain text.

Props

There are two ways to pass props to components using MDC.

Inline method

The {} identifier passes props to components in a terse way by using a key=value syntax.

index.md
::alert{type="warning"}The **alert** component.::
Alert.vue
<script setup>defineProps(['type'])</script><template>  <div :class="[type]">    <ContentSlot :use="$slots.default" unwrap="p" />  </div></template>
The alert component.

Multiple props can be separated with a space:

::alert{type="warning" icon="exclamation-circle"}Oops! An error occurred::

The v-bind shorthand : can be also be used to bind a prop to a value in the front matter.

---type: "warning"---::alert{:type="type"}Your warning::

If you want to pass arrays or objects as props to components you can pass them as JSON string and prefix the prop key with a colon to automatically decode the JSON string. Note that in this case you should use single quotes for the value string so you can use double quotes to pass a valid JSON string:

array.md
::dropdown{:items='["Nuxt", "Vue", "React"]'}::
number-array.md
::dropdown{:items='[1,2,3.5]'}::
object.md
::chart{:options='{"responsive": true, "scales": {"y": {"beginAtZero": true}}}'}::

YAML method

The YAML method uses the --- identifier to declare one prop per line, that can be useful for readability.

index.md
::icon-card---icon: IconNuxtdescription: Harness the full power of Nuxt and the Nuxt ecosystem.title: Nuxt Architecture.---::
IconCard.vue
<script setup>defineProps({  title: {    type: String,    default: 'Default title'  },  description: {    type: String,    default: 'Default description'  },  icon: {    type: String,    default: 'IconMarkdown'  }})</script><template>  <div class="p-6 border bg-white dark:bg-black dark:border-gray-700 rounded">    <component :is="icon" class="w-20 h-20" />    <h2 class="text-3xl font-semibold mb-2">      {{ title }}    </h2>    <p>{{ description }}</p>  </div></template>

Nuxt Architecture.

Harness the full power of Nuxt and the Nuxt ecosystem.

Span Text

To create inline spans in your text you can use the [] identifier.

Code
Hello [World]{style="background-color: var(--color-primary-500)"}!

Hello World!

Attributes

Attributes are useful for highlighting and modifying part of paragraph. The syntax is nearly similar to inline components and markdown links syntax.

Possible values ​​are all named attributes, classes with the notation .class-name and an ID with #id-name.

Code
Hello [World]{style="color: var(--color-primary-500)" .custom-class #custom-id}!

Hello World!

In addition to mdc components and spans, attribute syntax will work on images, links, inline code, bold and italic text.

Code
Attributes work on:- ![](/favicon.ico){style="display: inline; margin: 0; background-color: var(--color-primary-800);"} image,- [link](#attributes){style="background-color: var(--color-primary-400);"}, `code`{style="color: var(--color-primary-500);"},- _italic_{style="background-color: var(--color-primary-500);"} and **bold**{style="background-color: var(--color-primary-500);"} texts.

Attributes work on:

  • image,
  • link, code,
  • italic and bold texts.