18. @nuxt/content
📝 Модуль @nuxt/content
Заголовок раздела «📝 Модуль @nuxt/content»@nuxt/content — официальный модуль Nuxt для создания файловой CMS. Он позволяет хранить контент в виде Markdown, MDX, JSON и YAML файлов и запрашивать его через мощный API.
🚀 Установка и настройка
Заголовок раздела «🚀 Установка и настройка»npx nuxi module add contentexport default defineNuxtConfig({ modules: ['@nuxt/content'], content: { // Подсветка синтаксиса через Shiki highlight: { theme: { default: 'github-dark', dark: 'github-dark', light: 'github-light' }, langs: ['js', 'ts', 'vue', 'jsx', 'tsx', 'bash', 'json', 'css', 'html', 'python'] }, // MDC (Markdown Components) синтаксис markdown: { anchorLinks: true, remarkPlugins: ['remark-emoji'], rehypePlugins: ['rehype-figure'] }, // Настройка директории sources: { content: { driver: 'fs', base: resolve(__dirname, 'content') } } }})📁 Структура директории content/
Заголовок раздела «📁 Структура директории content/»content/├── index.md # /├── about.md # /about├── blog/│ ├── _dir.yml # метаданные директории│ ├── first-post.md # /blog/first-post│ └── second-post.mdx # /blog/second-post├── docs/│ ├── 1.getting-started.md│ ├── 2.configuration.md│ └── 3.deployment.md└── data/ ├── team.json └── config.yaml📄 Frontmatter
Заголовок раздела «📄 Frontmatter»Frontmatter — метаданные в начале файла в формате YAML:
---title: "Моя первая статья"description: "Описание для SEO"date: 2024-01-15author: "Александр"tags: ['nuxt', 'vue', 'tutorial']image: '/images/cover.jpg'draft: falsefeatured: true---
Текст статьи...Доступ к frontmatter в компонентах:
<script setup lang="ts">const { data: article } = await useAsyncData('article', () => queryCollection('blog').path('/blog/first-post').first())
// article.value.title// article.value.description// article.value.date</script>🔍 queryCollection
Заголовок раздела «🔍 queryCollection»Основной способ получения контента (Nuxt Content v3):
// Получение одного документаconst article = await queryCollection('blog') .path('/blog/my-post') .first()
// Получение всех документовconst articles = await queryCollection('blog') .order('date', 'DESC') .limit(10) .all()
// Фильтрацияconst featured = await queryCollection('blog') .where('featured', '=', true) .where('draft', '=', false) .order('date', 'DESC') .all()
// Поискconst results = await queryCollection('blog') .where('title', 'LIKE', '%nuxt%') .all()🖥️ Компонент ContentDoc
Заголовок раздела «🖥️ Компонент ContentDoc»<ContentDoc> автоматически находит и рендерит документ по текущему пути:
<template> <article> <ContentDoc> <template #default="{ doc }"> <h1>{{ doc.title }}</h1> <time>{{ doc.date }}</time> <ContentRenderer :value="doc" /> </template>
<template #not-found> <div>Статья не найдена</div> </template>
<template #empty> <div>Пустой документ</div> </template> </ContentDoc> </article></template>🎨 ContentRenderer
Заголовок раздела «🎨 ContentRenderer»<ContentRenderer> рендерит Markdown/MDX контент:
<script setup lang="ts">const { data: doc } = await useAsyncData( useRoute().path, () => queryCollection('docs').path(useRoute().path).first())</script>
<template> <div> <h1>{{ doc.title }}</h1> <ContentRenderer :value="doc" class="prose" /> </div></template>🧩 MDC — Markdown Components
Заголовок раздела «🧩 MDC — Markdown Components»MDC позволяет использовать Vue-компоненты прямо в Markdown:
# Документация
Обычный текст **Markdown**.
::callout{type="warning"}Это важное предупреждение!::
::code-group```typescript [nuxt.config.ts]export default defineNuxtConfig({ modules: ['@nuxt/content']})```
```bash [Terminal]npx nuxi module add content```::
:badge[Новое в v3]{color="green"}
::card{title="Заголовок карточки"}Содержимое карточки с **форматированием**.::Создание MDC компонентов
Заголовок раздела «Создание MDC компонентов»<script setup lang="ts">defineProps<{ type?: 'info' | 'warning' | 'danger' | 'success'}>()</script>
<template> <div :class="`callout callout-${type ?? 'info'}`"> <slot /> </div></template>
<style scoped>.callout { padding: 16px; border-radius: 8px; }.callout-warning { background: #fef3c7; border-left: 4px solid #f59e0b; }.callout-danger { background: #fee2e2; border-left: 4px solid #ef4444; }.callout-success { background: #d1fae5; border-left: 4px solid #10b981; }.callout-info { background: #dbeafe; border-left: 4px solid #3b82f6; }</style>📊 Работа с JSON и YAML
Заголовок раздела «📊 Работа с JSON и YAML»[ { "name": "Александр", "role": "Frontend Developer", "avatar": "/images/alex.jpg" }, { "name": "Мария", "role": "Backend Developer", "avatar": "/images/maria.jpg" }]// Получение JSON данныхconst team = await queryCollection('data') .path('/data/team') .first()// team.body — массив сотрудников🔗 Навигация по документам
Заголовок раздела «🔗 Навигация по документам»<script setup lang="ts">// Получение предыдущего и следующего документаconst { data: surround } = await useAsyncData( `surround-${useRoute().path}`, () => queryCollectionItemSurroundings('docs', useRoute().path, { fields: ['title', 'description'] }))
const [prev, next] = surround.value ?? []</script>
<template> <nav> <NuxtLink v-if="prev" :to="prev.path"> ← {{ prev.title }} </NuxtLink> <NuxtLink v-if="next" :to="next.path"> {{ next.title }} → </NuxtLink> </nav></template>🎯 Подсветка синтаксиса
Заголовок раздела «🎯 Подсветка синтаксиса»Shiki обеспечивает красивую подсветку в code-блоках:
```typescript [filename.ts] {2,4}const x = 1 // обычная строкаconst y = 2 // подсвеченная строкаconst z = 3 // обычная строкаconst w = 4 // подсвеченная строка```Параметры code-блоков:
- Язык:
typescript,vue,bash - Имя файла:
[filename.ts] - Подсветка строк:
{1,3-5}
📋 Таблица возможностей
Заголовок раздела «📋 Таблица возможностей»| Формат | Поддержка | Особенности |
|---|---|---|
.md | ✅ | Стандартный Markdown |
.mdx | ✅ | Markdown + JSX компоненты |
.json | ✅ | Данные в JSON формате |
.yaml | ✅ | Данные в YAML формате |
.csv | ✅ | Табличные данные |
| Frontmatter | ✅ | YAML метаданные |
| MDC | ✅ | Vue компоненты в Markdown |
| Shiki | ✅ | Подсветка 100+ языков |