Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
397 changes: 397 additions & 0 deletions docs/content/3.rendering/3.nuxt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,397 @@
---
title: Nuxt
description: Learn how to use MDC Syntax in a Nuxt application.
---

Render MDC content in Nuxt applications with automatic component registration. The `mdc-syntax/nuxt` module provides zero-config setup with auto-imported components and Nuxt UI integration.

## Installation

```bash
npm install mdc-syntax
```

Add the module to your `nuxt.config.ts`:

```typescript
export default defineNuxtConfig({
modules: ['mdc-syntax/nuxt']
})
```

---

## What the Module Does

The `mdc-syntax/nuxt` module automatically:

1. **Auto-imports Components** - Registers `<MDC>` and `<MDCRenderer>` components globally
2. **Registers Component Directory** - Makes `~/components/mdc` a global components directory for custom prose components
3. **Detects Nuxt UI** - Automatically configures Nuxt UI prose components when `@nuxt/ui` is installed
4. **Server-Side Support** - Full SSR/SSG compatibility

---

## MDC Component

The `MDC` component is automatically available in all your templates without imports. Pass markdown content and it handles parsing and rendering.

### Basic Usage

```vue
<template>
<MDC markdown="# Hello *World*" />
</template>
```

### With Reactive Content

```vue
<script setup>
const content = ref(`# Hello World

This is **markdown** with MDC components.

::alert{type="info"}
This is an alert!
::
`)
</script>

<template>
<MDC :markdown="content" />
</template>
```

### Props

| Prop | Type | Description |
|------|------|-------------|
| `markdown` | `string` | Markdown content to parse and render |
| `components` | `Record<string, Component>` | Custom component mappings |
| `excerpt` | `boolean` | Only render content before `<!-- more -->` |

### With Custom Components

```vue
<script setup>
import CustomAlert from '~/components/Alert.vue'
import CustomCard from '~/components/Card.vue'

const components = {
alert: CustomAlert,
card: CustomCard,
}

const content = `
::alert{type="warning"}
Important message here
::

::card{title="My Card"}
Card content
::
`
</script>

<template>
<MDC :markdown="content" :components="components" />
</template>
```

### Excerpt Mode

Render only content before `<!-- more -->`:

```vue
<script setup>
const content = `# Article Title

This is the excerpt shown in listings.

<!-- more -->

This is the full article content.
`
</script>

<template>
<!-- Only renders "This is the excerpt shown in listings." -->
<MDC :markdown="content" excerpt />
</template>
```

---

## MDCRenderer Component

The `MDCRenderer` component renders a pre-parsed Minimark AST. Use this when you need more control over parsing or are working with server-fetched content.

### Basic Usage

```vue
<script setup>
import { parse } from 'mdc-syntax'

const content = `# Hello World

This is **markdown** with MDC components.
`

const result = parse(content)
</script>

<template>
<MDCRenderer :body="result.body" />
</template>
```

### Props

| Prop | Type | Description |
|------|------|-------------|
| `body` | `MinimarkTree` | Required. The parsed AST to render |
| `components` | `Record<string, Component>` | Custom component mappings |
| `componentsManifest` | `(name: string) => Promise<Component> | null` | Dynamic component loader |

### With Server Data

```vue
<script setup>
const { data } = await useFetch('/api/content', {
transform: (content) => parse(content).body
})
</script>

<template>
<MDCRenderer :body="data" />
</template>
```

### Streaming Support

`MDCRenderer` works with `parseStreamIncremental` for real-time content:

```vue
<script setup>
import { parseStreamIncremental } from 'mdc-syntax/stream'

const body = ref({ type: 'minimark', value: [] })
const isComplete = ref(false)

async function loadContent() {
const response = await fetch('/api/content')

for await (const result of parseStreamIncremental(response.body!)) {
body.value = result.body

if (result.isComplete) {
isComplete.value = true
}
}
}

onMounted(() => loadContent())
</script>

<template>
<div>
<MDCRenderer :body="body" />
<div v-if="!isComplete" class="loading">
Streaming content...
</div>
</div>
</template>
```

---

## Custom Prose Components

Override default HTML element rendering by creating components in the `~/components/mdc` directory. These components are automatically registered and used by the MDC renderer.

### Directory Structure

```
~/components/
mdc/
Alert.vue
Card.vue
H1.vue
H2.vue
Pre.vue
```

### Creating Custom Components

```vue
<!-- ~/components/mdc/Alert.vue -->
<script setup>
defineProps<{
type?: 'info' | 'warning' | 'error' | 'success'
}>()
</script>

<template>
<div class="alert" :class="`alert-${type || 'info'}`" role="alert">
<slot />
</div>
</template>

<style scoped>
.alert { padding: 1rem; border-radius: 0.5rem; }
.alert-info { background: #e3f2fd; }
.alert-warning { background: #fff3e0; }
.alert-error { background: #ffebee; }
.alert-success { background: #e8f5e9; }
</style>
```

**Usage in markdown:**

```markdown
::alert{type="warning"}
This is a warning message!
::
```

### Overriding HTML Elements

```vue
<!-- ~/components/mdc/H1.vue -->
<script setup>
const props = defineProps<{
id?: string
}>()
</script>

<template>
<h1 :id="id" class="heading">
<a v-if="id" :href="`#${id}`" class="anchor">#</a>
<slot />
</h1>
</template>
```

Components in `~/components/mdc` with lowercase names (h1, h2, p, etc.) automatically override HTML elements.

---

## Nuxt UI Integration

When `@nuxt/ui` is installed, MDC Syntax automatically uses Nuxt UI's prose components for enhanced styling.

### Installation

```bash
npm install @nuxt/ui
```

```typescript
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['mdc-syntax/nuxt', '@nuxt/ui']
})
```

### Auto-Detection

The `mdc-syntax/nuxt` module detects Nuxt UI and:
- Registers Nuxt UI's prose components automatically
- Uses Nuxt UI styling for all HTML elements
- Provides consistent design with your Nuxt UI setup

### Example Setup

```vue
<!-- app.vue -->
<script setup>
const markdown = `
# MDC + Nuxt UI

MDC Syntax automatically detects Nuxt UI and uses its components for rendering.

::u-alert{type="info"}
This alert uses Nuxt UI styling!
::
`
</script>

<template>
<MDC :markdown="markdown" />
</template>
```

### CSS Setup

```css
/* app/assets/css/main.css */
@import "tailwindcss";
@import "@nuxt/ui";
```

```typescript
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['mdc-syntax/nuxt', '@nuxt/ui'],
css: ['~/assets/css/main.css']
})
```

---

## Server-Side Rendering

MDC Syntax fully supports SSR and SSG in Nuxt:

### Static Generation

```vue
<script setup>
// Content is parsed at build time
const content = `# Static Content

This is rendered at build time.
`
</script>

<template>
<MDC :markdown="content" />
</template>
```

### Dynamic SSR

```vue
<script setup>
// Fetch and render on the server
const { data: content } = await useFetch('/api/article')
</script>

<template>
<MDC v-if="content" :markdown="content" />
</template>
```

### Prerendering

```typescript
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['mdc-syntax/nuxt'],
nitro: {
prerender: {
routes: ['/blog', '/docs']
}
}
})
```

---

## See Also

- [Vue Renderer](/rendering/vue) - Vue component API
- [React Renderer](/rendering/react) - React integration
- [Parse API](/api/parse) - Parsing options and streaming
- [MDC Syntax](/syntax/markdown) - Markdown component syntax
Loading
Loading