Zum Hauptinhalt springen

Eine eigene Markdown-Komponente hinzufügen

Eine globale Vue-Komponente registrieren, ihr MDC-Tag abbilden, eine enge Content-Policy deklarieren und sie optional für Agenten serialisieren.

Ein eigenes MDC-Tag überschreitet drei explizite Grenzen: Vue rendert es, die Markdown-Tag-Map löst es auf und die Component Policy entscheidet, welche Eingaben aus dem Content sicher sind. Ergänze nur dann einen Agenten-Serializer, wenn die visuelle Komponente eine andere Textdarstellung benötigt.

Dieses Beispiel ergänzt ::api-playground mit erforderlicher HTTP-Methode und erforderlichem Pfad.

Die Vue-Komponente erstellen

app/components/mdc/MdcApiPlayground.vue
<script setup lang="ts">
defineProps<{
  method: string;
  path: string;
}>();
</script>

<template>
  <section class="not-prose rounded-lg border border-border p-5">
    <p class="font-mono text-sm font-semibold">{{ method }} {{ path }}</p>
    <div class="mt-3 text-sm text-muted-foreground">
      <slot />
    </div>
  </section>
</template>

MDC löst Tag-Ziele dynamisch auf. Registriere die Komponente deshalb global in einem kleinen Nuxt-Plugin:

app/plugins/mdc-components.ts
import MdcApiPlayground from "~/components/mdc/MdcApiPlayground.vue";

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.component("MdcApiPlayground", MdcApiPlayground);
});

Eine .global.vue-Komponente ist eine Alternative. Füge keine zweite Docs-spezifische Komponentenregistrierung hinzu.

Tag-Map und Policy erweitern

Behalte die integrierten Zuordnungen des Layers und ergänze dann das verfasste Tag. Deklariere nur die Props und Slots, die diese Komponente benötigt:

nuxt.config.ts
import { ginkoDocsComponentTags } from "@lupinum/ginko-docs/components";

export default defineNuxtConfig({
  extends: ["@lupinum/ginko-docs"],
  content: {
    componentPolicy: {
      components: {
        "api-playground": {
          kind: "block",
          props: {
            method: { type: "string", required: true },
            path: { type: "string", required: true },
          },
          slots: ["default"],
          media: null,
        },
      },
    },
    markdown: {
      tags: {
        ...ginkoDocsComponentTags,
        "api-playground": "MdcApiPlayground",
      },
    },
  },
});

Die Policy ist die öffentliche Autorengrenze, kein bequemes Datenschema. Dynamische Vue-Bindings bleiben in öffentlichem Markdown abgelehnt. Vermeide breite Prop-Sammlungen, beliebige Slots oder Medienzugriff, solange die Komponente dafür keinen konkreten Zweck hat.

Autoren können das Tag jetzt verwenden:

content/docs/api.md
::api-playground{method="GET" path="/v1/projects"}
Gibt die Projekte zurück, die für das aktuelle Token sichtbar sind.
::

Agenten-Markdown bei Bedarf ergänzen

Der standardmäßige Agenten-Renderer hält unbekannte Komponentenstrukturen explizit. Registriere nur dann einen Serializer, wenn eine kompakte Textform hilfreicher ist. Der Serializer läuft auf dem Server und muss deterministische öffentliche Inhalte zurückgeben.

server/plugins/api-playground-markdown.ts
import {
  registerAgentMarkdownSerializers,
  type AgentMarkdownSerializer,
} from "@lupinum/ginko-content/agent-registry";
import { defineNitroPlugin } from "nitropack/runtime";

const apiPlaygroundMarkdown: AgentMarkdownSerializer = (node, context) => {
  const props = context.cleanProps(node);
  const method = String(props.method || "GET");
  const path = String(props.path || "/");
  const details = context.renderChildren(node).trim();

  return [`**${method} ${path}**`, details].filter(Boolean).join("\n\n");
};

export default defineNitroPlugin(() => {
  registerAgentMarkdownSerializers({
    "api-playground": apiPlaygroundMarkdown,
    MdcApiPlayground: apiPlaygroundMarkdown,
  });
});

Registriere das verfasste Tag und den Komponentenalias, weil der geparste Baum beide Namen enthalten kann. Teste die gerenderte Komponente und ihre /raw/**.md-Ausgabe vor der Veröffentlichung. Die Referenz zur Content-Konfiguration beschreibt die Form der Policy.