EmDash bietet Abfragefunktionen zum Abrufen von Inhalten in Ihren Astro-Seiten und -Komponenten. Diese Funktionen folgen Astros Live Content Collections-Muster und geben strukturierte Ergebnisse mit Fehlerbehandlung zurück.
Abfragefunktionen
EmDash exportiert zwei primäre Abfragefunktionen:
| Funktion | Zweck | Gibt zurück |
|---|---|---|
getEmDashCollection | Alle Einträge eines Inhaltstyps abrufen | { entries, error } |
getEmDashEntry | Einen einzelnen Eintrag nach ID oder Slug abrufen | { entry, error, isPreview } |
Importieren Sie sie aus emdash:
import { getEmDashCollection, getEmDashEntry } from "emdash";
Alle Einträge abrufen
Verwenden Sie getEmDashCollection, um alle Einträge eines Inhaltstyps abzurufen:
---
import { getEmDashCollection } from "emdash";
const { entries: posts, error } = await getEmDashCollection("posts");
if (error) {
console.error("Beiträge konnten nicht geladen werden:", error);
}
---
<ul>
{posts.map((post) => (
<li>{post.data.title}</li>
))}
</ul>
Nach Locale filtern
Wenn i18n aktiviert ist, filtern Sie nach Locale, um Inhalte in einer bestimmten Sprache abzurufen:
// Französische Beiträge
const { entries: frenchPosts } = await getEmDashCollection("posts", {
locale: "fr",
status: "published",
});
// Die aktuelle Anfrage-Locale verwenden
const { entries: localizedPosts } = await getEmDashCollection("posts", {
locale: Astro.currentLocale,
status: "published",
});
Für einzelne Einträge übergeben Sie locale als drittes Argument:
const { entry: post } = await getEmDashEntry("posts", "my-post", {
locale: Astro.currentLocale,
});
Wenn locale weggelassen wird, wird standardmäßig die aktuelle Locale der Anfrage verwendet. Wenn keine Übersetzung für die angeforderte Locale existiert, wird die Fallback-Kette befolgt.
Nach Status filtern
Nur veröffentlichte oder Entwurfsinhalte abrufen:
// Nur veröffentlichte Beiträge
const { entries: published } = await getEmDashCollection("posts", {
status: "published",
});
// Nur Entwürfe
const { entries: drafts } = await getEmDashCollection("posts", {
status: "draft",
});
Ergebnisse begrenzen
Die Anzahl der zurückgegebenen Einträge einschränken:
// Die 5 neuesten Beiträge abrufen
const { entries: recentPosts } = await getEmDashCollection("posts", {
status: "published",
limit: 5,
});
Nach Taxonomie filtern
Einträge nach Kategorie, Tag oder benutzerdefinierten Taxonomie-Begriffen filtern:
// Beiträge in der Kategorie "news"
const { entries: newsPosts } = await getEmDashCollection("posts", {
status: "published",
where: { category: "news" },
});
// Beiträge mit dem Tag "javascript"
const { entries: jsPosts } = await getEmDashCollection("posts", {
status: "published",
where: { tag: "javascript" },
});
// Beiträge, die einem von mehreren Begriffen entsprechen
const { entries: featuredNews } = await getEmDashCollection("posts", {
status: "published",
where: { category: ["news", "featured"] },
});
Der where-Filter verwendet ODER-Logik, wenn mehrere Werte für eine einzelne Taxonomie angegeben werden.
Fehlerbehandlung
Prüfen Sie immer auf Fehler, wenn Zuverlässigkeit wichtig ist:
const { entries: posts, error } = await getEmDashCollection("posts");
if (error) {
// Protokollieren und elegant behandeln
console.error("Beiträge konnten nicht geladen werden:", error);
return new Response("Serverfehler", { status: 500 });
}
Einzelnen Eintrag abrufen
Verwenden Sie getEmDashEntry, um einen Eintrag nach ID oder Slug abzurufen:
---
import { getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";
const { slug } = Astro.params;
const { entry: post, error } = await getEmDashEntry("posts", slug);
if (error) {
return new Response("Serverfehler", { status: 500 });
}
if (!post) {
return Astro.redirect("/404");
}
---
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>
Eintrags-Rückgabetyp
getEmDashEntry gibt ein Ergebnisobjekt zurück:
interface EntryResult<T> {
entry: ContentEntry<T> | null; // null, wenn nicht gefunden
error?: Error; // Nur bei tatsächlichen Fehlern gesetzt (nicht bei "nicht gefunden")
isPreview: boolean; // true, wenn Vorschau-/Entwurfsinhalte angezeigt werden
}
interface ContentEntry<T> {
id: string;
data: T;
edit: EditProxy; // Visuelles Editing-Annotationen
}
Das data-Objekt innerhalb von entry enthält alle für den Inhaltstyp definierten Felder. Der edit-Proxy bietet visuelle Editing-Annotationen (siehe unten).
SEO-Panel-Daten rendern
Für Sammlungen mit supports: ["seo"] können Redakteure einen SEO-Titel, eine Meta-Beschreibung, ein OG-Bild, eine kanonische URL und einen „Von Suchmaschinen verstecken”-Toggle (noindex) im SEO-Panel des Admins setzen. Diese Daten werden als entry.data.seo im Eintrag geliefert — erreichen aber die gerenderte Seite nur, wenn Ihr Template sie ausgibt. Verwenden Sie getSeoMeta, um die Panel-Felder (mit sinnvollen Fallbacks auf data.title / data.excerpt) in renderfertige Meta-Tags aufzulösen:
---
import { getEmDashEntry, getSeoMeta } from "emdash";
const { entry, error } = await getEmDashEntry("posts", Astro.params.slug);
if (error) {
return new Response("Serverfehler", { status: 500 });
}
if (!entry) return Astro.redirect("/404");
const seo = getSeoMeta(entry, {
siteTitle: "Meine Seite",
siteUrl: "https://example.com",
path: Astro.url.pathname,
});
---
<head>
<title>{seo.title}</title>
{seo.description && <meta name="description" content={seo.description} />}
{seo.ogImage && <meta property="og:image" content={seo.ogImage} />}
{seo.canonical && <link rel="canonical" href={seo.canonical} />}
{seo.robots && <meta name="robots" content={seo.robots} />}
</head>
Vorschaumodus
EmDash behandelt die Vorschau automatisch über Middleware. Wenn eine URL ein gültiges _preview-Token enthält, verifiziert die Middleware es und richtet den Anfrage-Kontext ein. Ihre Abfragefunktionen liefern dann Entwurfsinhalte ohne spezielle Parameter:
---
import { getEmDashEntry } from "emdash";
const { slug } = Astro.params;
const { entry, isPreview, error } = await getEmDashEntry("posts", slug);
if (error) {
return new Response("Serverfehler", { status: 500 });
}
if (!entry) {
return Astro.redirect("/404");
}
---
{isPreview && (
<div class="preview-banner">
Vorschau wird angezeigt. Dieser Inhalt ist nicht veröffentlicht.
</div>
)}
<article>
<h1>{entry.data.title}</h1>
<PortableText value={entry.data.content} />
</article>
Visuelles Editing
Jeder von Abfragefunktionen zurückgegebene Eintrag enthält einen edit-Proxy zur Annotation Ihrer Templates. Spreaden Sie ihn auf Elemente, um Inline-Editing für authentifizierte Redakteure zu aktivieren:
<article {...entry.edit}>
<h1 {...entry.edit.title}>{entry.data.title}</h1>
<div {...entry.edit.content}>
<PortableText value={entry.data.content} />
</div>
</article>
Im Bearbeitungsmodus erzeugt {...entry.edit.title} ein data-emdash-ref-Attribut, das die visuelle Editing-Werkzeugleiste für Inline-Editing verwendet. In der Produktion erzeugen die Proxy-Spreads keine Ausgabe.
Inline-Codeblöcke stylen
Inline-Codeblöcke folgen standardmäßig dem hellen oder dunklen Erscheinungsbild des Systems. Wenn Ihre Seite einen eigenen Theme-Schalter hat, setzen Sie diese Eigenschaften in dessen hellen und dunklen Theme-Selektoren:
| Eigenschaft | Zweck |
|---|---|
--emdash-inline-code-background | Codeblock-Hintergrund |
--emdash-inline-code-foreground | Einfacher Code-Text |
--emdash-inline-code-muted | Kommentare und zitierter Text |
--emdash-inline-code-keyword | Schlüsselwörter, Literale, Selektoren und gelöschter Text |
--emdash-inline-code-string | Strings, Attribute, Symbole und hinzugefügter Text |
--emdash-inline-code-number | Zahlen und Metadaten |
--emdash-inline-code-title | Titel, Namen, Typen und Built-ins |
--emdash-inline-code-border | Sprachselektor-Rand |
--emdash-inline-code-control-background | Sprachselektor-Hintergrund |
--emdash-inline-code-control-foreground | Sprachselektor-Text und -Icons |
--emdash-inline-code-focus | Tastaturfokus-Indikator |
Das folgende Beispiel stylt Inline-Codeblöcke für eine Seite, die .dark auf das <html>-Element anwendet:
:root {
--emdash-inline-code-background: #f7f7f5;
--emdash-inline-code-foreground: #24292f;
--emdash-inline-code-muted: #57606a;
--emdash-inline-code-keyword: #b8172a;
--emdash-inline-code-string: #0a3069;
--emdash-inline-code-number: #0550ae;
--emdash-inline-code-title: #7545c7;
--emdash-inline-code-border: #7d8590;
--emdash-inline-code-control-background: #fff;
--emdash-inline-code-control-foreground: #24292f;
--emdash-inline-code-focus: #0550ae;
}
:root.dark {
--emdash-inline-code-background: #202020;
--emdash-inline-code-foreground: #f0f3f6;
--emdash-inline-code-muted: #c9d1d9;
--emdash-inline-code-keyword: #ffc1bb;
--emdash-inline-code-string: #b9ddff;
--emdash-inline-code-number: #a8d5ff;
--emdash-inline-code-title: #e5ccff;
--emdash-inline-code-border: #6e7681;
--emdash-inline-code-control-background: #161b22;
--emdash-inline-code-control-foreground: #f0f3f6;
--emdash-inline-code-focus: #a8d5ff;
}
Wenn Sie den Codeblock-Hintergrund ändern, überschreiben Sie auch jede Textfarbe, damit die Syntax lesbar bleibt. Diese Eigenschaften gelten nur, während Inline-Editing aktiv ist. Stylen Sie veröffentlichte Codeblöcke mit dem CSS Ihrer Seite.
Ergebnisse sortieren
getEmDashCollection garantiert keine Sortierreihenfolge. Sortieren Sie Ergebnisse in Ihrem Template:
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
// Nach Veröffentlichungsdatum sortieren, neueste zuerst
const sorted = posts.sort(
(a, b) => (b.data.publishedAt?.getTime() ?? 0) - (a.data.publishedAt?.getTime() ?? 0),
);
Häufige Sortiermuster
// Alphabetisch nach Titel
posts.sort((a, b) => a.data.title.localeCompare(b.data.title));
// Nach benutzerdefiniertem Reihenfolge-Feld
posts.sort((a, b) => (a.data.order ?? 0) - (b.data.order ?? 0));
// Zufällige Reihenfolge
posts.sort(() => Math.random() - 0.5);
TypeScript-Typen
Generieren Sie TypeScript-Typen für Ihre Sammlungen:
npx emdash types
Dies erstellt .emdash/types.ts mit Interfaces für jede Sammlung. Verwenden Sie sie für Typsicherheit:
import { getEmDashCollection, getEmDashEntry } from "emdash";
import type { Post } from "../.emdash/types";
// Typsichere Sammlungsabfrage
const { entries: posts } = await getEmDashCollection<Post>("posts");
// Typsichere Eintragsabfrage
const { entry: post } = await getEmDashEntry<Post>("posts", "my-post");
Statisches vs. Server-Rendering
EmDash-Inhalte funktionieren sowohl mit statisch als auch mit server-gerenderten Seiten.
Statisch (Vorgerendert)
Für statische Seiten verwenden Sie getStaticPaths, um Routen zur Build-Zeit zu generieren:
---
import { getEmDashCollection, getEmDashEntry } from "emdash";
export async function getStaticPaths() {
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
return posts.map((post) => ({
params: { slug: post.data.slug },
}));
}
const { slug } = Astro.params;
const { entry: post } = await getEmDashEntry("posts", slug);
---
Server-gerendert
Für server-gerenderte Seiten fragen Sie Inhalte direkt ab:
---
export const prerender = false;
import { getEmDashEntry } from "emdash";
const { slug } = Astro.params;
const { entry: post, error } = await getEmDashEntry("posts", slug);
if (error) {
return new Response("Serverfehler", { status: 500 });
}
if (!post) {
return new Response(null, { status: 404 });
}
---
Leistungsaspekte
Caching
EmDash verwendet Astros Live Content Collections, die das Caching automatisch handhaben. Für server-gerenderte Seiten sollten Sie HTTP-Cache-Header hinzufügen:
---
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
// 5 Minuten cachen
Astro.response.headers.set("Cache-Control", "public, max-age=300");
---
Redundante Abfragen vermeiden
Einmal abfragen und Daten an Komponenten übergeben:
---
import { getEmDashCollection } from "emdash";
import PostList from "../components/PostList.astro";
import Sidebar from "../components/Sidebar.astro";
// Einmal abfragen
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
const featured = posts.filter((p) => p.data.featured);
const recent = posts.slice(0, 5);
---
<PostList posts={featured} />
<Sidebar posts={recent} />
Nächste Schritte
- Blog erstellen - Einen vollständigen Blog aufbauen
- Taxonomien - Nach Kategorien und Tags filtern
- Mit Inhalten arbeiten - Admin-CRUD-Operationen
- Internationalisierung - Mehrsprachige Inhalte und Übersetzungen