Skip to main content

Components

Public components for parsed and inline Markdown.

The Nuxt module registers ContentRenderer and ContentRendererInline globally.

<ContentRenderer>

Render the Markdown body or excerpt from a parsed content document.

vue
<ContentRenderer :value="page" />
PropTypeDefaultPurpose
valueobject{}Full document, Markdown root, or object with body/excerpt
tagstring'div'Wrapper element
excerptbooleanfalseRender excerpt instead of body
prosebooleanruntime settingEnable prose-component mappings
unwrapboolean | stringfalseRemove matching wrapper tags
classVue class valuenoneClass forwarded to the renderer

The default slot replaces normal rendering and receives the props plus inherited attributes. The empty slot is used when the selected body is absent, unsupported, or has no children:

vue
<ContentRenderer :value="page">
  <template #empty>
    <p>No content found.</p>
  </template>
</ContentRenderer>

Without an empty slot, unsupported values render nothing and produce a console warning. Setting excerpt without an excerpt also warns.

<ContentRendererInline>

Parse and render a Markdown string inline.

vue
<ContentRendererInline value="Read the **release notes**." />
PropTypeDefaultPurpose
valuestringrequiredMarkdown source
tagstring'span'Wrapper element
unwrapboolean | string'p'Remove matching wrapper tags after parsing
prosebooleanruntime settingEnable prose-component mappings
componentsobject{}Per-render component overrides

The inline renderer intentionally uses a fixed safe baseline: standard Markdown, tables, task lists, and GFM alerts are normalized and validated before rendering; comments are discarded. Build-time Comark plugins, syntax highlighting, footnotes, Math, Mermaid, custom MDC components, and markdown.tags mappings apply only to ingested content, not to inline strings.

components may replace the renderer for a tag already authorized by that fixed baseline, such as strong or img. It does not authorize a new tag, component, prop, directive, or binding. For application components in ingested Markdown and their safe allowlist, see MDC and Vue components.

Both renderers resolve a tag in three steps: the per-render components prop, then the application's registered components, then the bundled prose defaults. Registering a global ProseImg component therefore replaces the built-in image rendering, including its markdown.image mode.

<ContentBodyRenderer>

Import the body renderer explicitly when a CMS or another content boundary already owns parsing and supplies a normalized Markdown body. It requires a component policy and an explicit component map. Use <ContentRenderer> for full Nuxt content documents that need collection and reference context.

This example parses a fixed preview string. For persisted content, parse and validate at the server or publishing boundary and pass the resulting body to the renderer.

app/components/BodyPreview.vue
<script setup lang="ts">
import ContentBodyRenderer from '@lupinum/ginko-content/body-renderer'
import { parseMdcBody } from '@lupinum/ginko-content/cms-contract'

const { body } = await parseMdcBody('## Preview\n\nRead **formatted text**.', {
  autoClose: false
})
const policy = { components: {} }
</script>

<template>
  <ContentBodyRenderer :body="body" :policy="policy" :components="{}" />
</template>

The renderer validates the body against the supplied V1 or V2 policy. A component map selects implementations; it does not authorize undeclared components or props. Optional props include fallbackComponents, tag, prose, locale, defaultLocale, locales, and dataContentId. The exported Vue declaration defines their exact types and defaults.