# Content

> Markdown, rendered with your components.

`<WriterContent>` renders Markdown, or a document parsed ahead of time. In plain Vue, import `WriterContent`.

## Examples

### Live preview

Markdown renders as you type; `debounce` waits a beat before parsing again.

```vue
<script setup lang="ts">
const body = ref(`## Rendered

Type on the left: **Markdown** renders on the right, blocks included.

::callout
A callout block.
::`);
</script>

<template>
  <div class="writer-demo writer-demo-split">
    <UiTextarea v-model="body" label="Markdown" />
    <WriterContent :value="body" :debounce="100" />
  </div>
</template>
```

## Props

| Prop         | Type                         | Description                                                          |
| ------------ | ---------------------------- | -------------------------------------------------------------------- |
| `value`      | `string \| MarkdownDocument` | Markdown, or a document parsed ahead of time (no parser download).   |
| `components` | `Record<string, Component>`  | Native element overrides for this render, e.g. `{ a: NuxtLink }`.    |
| `debounce`   | `number`                     | Ms to wait before parsing changed Markdown again. ~100 for previews. |
| `tag`        | `string`                     | Wrapper element. Default `div`.                                      |

Give it a parsed document on public pages: they render without loading the parser. A string works anywhere, server rendering included, and loads the parser on demand.

## What renders

- Markdown's own elements, and registered [blocks](/blocks). Anything else renders its content only.
- Images load lazily. An image alone in its paragraph, with a title, becomes a `<figure>`. See [Images](/images).
- Content is sanitized again before rendering. See [Security](/security).

## Your own wrapper

`renderDocument(document, { blocks, components })` returns the rendered Vue nodes, for when `<WriterContent>` doesn't fit. These docs render their pages with it.
