or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

collections.mdconfiguration.mdindex.mdnavigation-utilities.mdnavigation.mdpreview.mdquerying.mdrendering.mdruntime-utilities.md

rendering.mddocs/

0

# Content Rendering

1

2

Vue component system for rendering content with MDC (Markdown Components) support, custom component mapping, and prose styling. Enables rich content experiences with Vue components embedded in Markdown.

3

4

## Capabilities

5

6

### ContentRenderer Component

7

8

Primary component for rendering parsed content with full MDC support and customization options.

9

10

```typescript { .api }

11

interface ContentRendererProps {

12

/** Content object to render (required) */

13

value: object;

14

/** Render only excerpt portion of content */

15

excerpt?: boolean;

16

/** Root HTML tag for wrapper element */

17

tag?: string;

18

/** Custom component mapping for MDC rendering */

19

components?: Record<string, Component>;

20

/** Additional data passed to rendered components */

21

data?: Record<string, unknown>;

22

/** Use prose components instead of plain HTML tags */

23

prose?: boolean;

24

/** CSS classes for root element */

25

class?: string | Record<string, boolean>;

26

/** Tags to unwrap from rendered content */

27

unwrap?: boolean | string;

28

}

29

30

interface ContentRendererSlots {

31

/** Rendered when content value is empty or null */

32

empty(): VNode[];

33

}

34

```

35

36

**Usage Examples:**

37

38

```vue

39

<template>

40

<!-- Basic content rendering -->

41

<ContentRenderer :value="article" />

42

43

<!-- Render only excerpt -->

44

<ContentRenderer :value="article" excerpt />

45

46

<!-- Custom wrapper tag -->

47

<ContentRenderer :value="article" tag="article" />

48

49

<!-- Custom components for MDC -->

50

<ContentRenderer

51

:value="article"

52

:components="{

53

'custom-alert': AlertComponent,

54

'code-block': CodeBlockComponent

55

}"

56

/>

57

58

<!-- Pass additional data to components -->

59

<ContentRenderer

60

:value="article"

61

:data="{ author: currentUser, theme: 'dark' }"

62

/>

63

64

<!-- Use prose styling -->

65

<ContentRenderer :value="article" prose class="prose-lg" />

66

67

<!-- Handle empty content -->

68

<ContentRenderer :value="article">

69

<template #empty>

70

<p>No content available</p>

71

</template>

72

</ContentRenderer>

73

74

<!-- Unwrap specific tags -->

75

<ContentRenderer :value="article" unwrap="p" />

76

</template>

77

78

<script setup>

79

import AlertComponent from '~/components/Alert.vue';

80

import CodeBlockComponent from '~/components/CodeBlock.vue';

81

82

const { data: article } = await queryCollection('articles')

83

.path(useRoute().path)

84

.first();

85

</script>

86

```

87

88

### ContentPreviewMode Component

89

90

Component for enabling live content editing and preview functionality.

91

92

```typescript { .api }

93

interface ContentPreviewModeProps {

94

/** Authentication token for preview mode (required) */

95

previewToken: string;

96

/** API endpoint URL for preview data (required) */

97

api: string;

98

/** Preview initialization callback (required) */

99

initializePreview: (preview: PreviewInstance) => void;

100

}

101

102

interface PreviewInstance {

103

/** Enable preview mode */

104

enable(): void;

105

/** Disable preview mode */

106

disable(): void;

107

/** Check if preview is active */

108

isActive(): boolean;

109

/** Refresh preview data */

110

refresh(): Promise<void>;

111

}

112

```

113

114

**Usage Examples:**

115

116

```vue

117

<template>

118

<div>

119

<!-- Content with preview mode -->

120

<ContentRenderer :value="content" />

121

122

<!-- Preview mode component -->

123

<ContentPreviewMode

124

:preview-token="previewToken"

125

:api="previewApi"

126

:initialize-preview="handlePreviewInit"

127

/>

128

</div>

129

</template>

130

131

<script setup>

132

const previewToken = useCookie('preview-token');

133

const previewApi = '/api/preview';

134

135

let previewInstance: PreviewInstance;

136

137

const handlePreviewInit = (preview: PreviewInstance) => {

138

previewInstance = preview;

139

140

// Auto-enable preview if token exists

141

if (previewToken.value) {

142

preview.enable();

143

}

144

};

145

146

// Toggle preview mode

147

const togglePreview = () => {

148

if (previewInstance.isActive()) {

149

previewInstance.disable();

150

} else {

151

previewInstance.enable();

152

}

153

};

154

</script>

155

```

156

157

## MDC Component Integration

158

159

### Custom Component Registration

160

161

```typescript

162

// nuxt.config.ts

163

export default defineNuxtConfig({

164

content: {

165

renderer: {

166

// Global component mapping

167

components: {

168

'alert': '~/components/Alert.vue',

169

'code-sandbox': '~/components/CodeSandbox.vue',

170

'video-player': '~/components/VideoPlayer.vue'

171

}

172

}

173

}

174

});

175

```

176

177

### Component Usage in Markdown

178

179

```markdown

180

<!-- In your .md files -->

181

182

# My Article

183

184

Regular markdown content here.

185

186

::alert{type="warning"}

187

This is a custom alert component with props!

188

::

189

190

::code-sandbox{id="vue-example"}

191

::

192

193

::video-player{src="/videos/demo.mp4" autoplay}

194

::

195

```

196

197

### Custom Component Definition

198

199

```vue

200

<!-- components/Alert.vue -->

201

<template>

202

<div :class="alertClasses">

203

<icon :name="iconName" />

204

<div class="alert-content">

205

<slot />

206

</div>

207

</div>

208

</template>

209

210

<script setup>

211

interface Props {

212

type?: 'info' | 'warning' | 'error' | 'success';

213

title?: string;

214

}

215

216

const props = withDefaults(defineProps<Props>(), {

217

type: 'info'

218

});

219

220

const alertClasses = computed(() => [

221

'alert',

222

`alert-${props.type}`

223

]);

224

225

const iconName = computed(() => {

226

const icons = {

227

info: 'information-circle',

228

warning: 'exclamation-triangle',

229

error: 'x-circle',

230

success: 'check-circle'

231

};

232

return icons[props.type];

233

});

234

</script>

235

```

236

237

## Tree Processing

238

239

Low-level utilities for working with content AST and tree structures.

240

241

```typescript { .api }

242

/**

243

* Compresses MDC tree to minimark format for storage/transport

244

* @param input - MDC AST root node

245

* @returns Compressed minimark tree

246

*/

247

function compressTree(input: MDCRoot): MinimarkTree;

248

249

/**

250

* Decompresses minimark tree back to MDC format

251

* @param input - Compressed tree data

252

* @returns Full MDC AST root node

253

*/

254

function decompressTree(input: Tree): MDCRoot;

255

256

/**

257

* Tree traversal utility for AST manipulation

258

* @param tree - Tree to traverse

259

* @param checker - Function to test if node should be visited

260

* @param visitor - Function to transform matching nodes

261

*/

262

function visit(

263

tree: Tree,

264

checker: (node: Node) => boolean,

265

visitor: (node: Node) => Node | undefined

266

): void;

267

```

268

269

**Usage Examples:**

270

271

```typescript

272

import { compressTree, decompressTree, visit } from '@nuxt/content/runtime';

273

274

// Compress content for storage

275

const compressed = compressTree(content.body);

276

277

// Decompress for rendering

278

const fullTree = decompressTree(compressed);

279

280

// Transform nodes in tree

281

visit(tree,

282

(node) => node.type === 'element' && node.tag === 'img',

283

(node) => {

284

// Add lazy loading to images

285

if (node.props) {

286

node.props.loading = 'lazy';

287

}

288

return node;

289

}

290

);

291

```

292

293

## Types

294

295

```typescript { .api }

296

interface MDCRoot {

297

type: 'root';

298

children: MDCNode[];

299

}

300

301

interface MDCNode {

302

type: string;

303

tag?: string;

304

props?: Record<string, unknown>;

305

children?: MDCNode[];

306

value?: string;

307

}

308

309

interface MinimarkTree {

310

type: 'root';

311

children: MinimarkNode[];

312

}

313

314

interface MinimarkNode {

315

type: string;

316

tag?: string;

317

props?: Record<string, unknown>;

318

children?: MinimarkNode[];

319

value?: string;

320

}

321

322

type Tree = MDCRoot | MinimarkTree;

323

type Node = MDCNode | MinimarkNode;

324

325

interface Component {

326

name: string;

327

props?: Record<string, unknown>;

328

slots?: Record<string, () => VNode[]>;

329

}

330

```