Aller au contenu

Interroger le Contenu

EmDash fournit des fonctions de requête pour récupérer du contenu dans vos pages et composants Astro. Ces fonctions suivent le modèle des collections de contenu en direct d’Astro, renvoyant des résultats structurés avec gestion des erreurs.

EmDash exporte deux fonctions de requête principales :

FonctionObjectifRetourne
getEmDashCollectionRécupérer toutes les entrées d’un type de contenu{ entries, error }
getEmDashEntryRécupérer une seule entrée par ID ou slug{ entry, error, isPreview }

Importez-les depuis emdash :

import { getEmDashCollection, getEmDashEntry } from "emdash";

Utilisez getEmDashCollection pour récupérer toutes les entrées d’un type de contenu :

astro title="src/pages/posts.astro"
---
import { getEmDashCollection } from "emdash";
const { entries: posts, error } = await getEmDashCollection("posts");
if (error) {
console.error("Failed to load posts:", error);
}
---
<ul>
{posts.map((post) => (
<li>{post.data.title}</li>
))}
</ul>

Lorsque l’i18n est activé, filtrez par langue pour récupérer le contenu dans une langue spécifique :

// French posts
const { entries: frenchPosts } = await getEmDashCollection("posts", {
locale: "fr",
status: "published",
});
// Utilise la langue de la requête courante
const { entries: localizedPosts } = await getEmDashCollection("posts", {
locale: Astro.currentLocale,
status: "published",
});

Pour les entrées individuelles, passez locale comme troisième argument :

const { entry: post } = await getEmDashEntry("posts", "my-post", {
locale: Astro.currentLocale,
});

Lorsque locale est omis, il prend par défaut la langue courante de la requête. Si aucune traduction n’existe pour la langue demandée, la chaîne de repli est suivie.

Récupérez uniquement le contenu publié ou en brouillon :

// Only published posts
const { entries: published } = await getEmDashCollection("posts", {
status: "published",
});
// Seulement les brouillons
const { entries: drafts } = await getEmDashCollection("posts", {
status: "draft",
});

Restreignez le nombre d’entrées retournées :

// Get the 5 most recent posts
const { entries: recentPosts } = await getEmDashCollection("posts", {
status: "published",
limit: 5,
});

Filtrez les entrées par catégorie, étiquette ou termes de taxonomie personnalisés :

// Posts in the "news" category
const { entries: newsPosts } = await getEmDashCollection("posts", {
status: "published",
where: { category: "news" },
});
// Articles avec l'étiquette "javascript"
const { entries: jsPosts } = await getEmDashCollection("posts", {
status: "published",
where: { tag: "javascript" },
});
// Articles correspondant à l'un des multiples termes
const { entries: featuredNews } = await getEmDashCollection("posts", {
status: "published",
where: { category: ["news", "featured"] },
});

Le filtre where utilise une logique OU lorsque plusieurs valeurs sont fournies pour une seule taxonomie.

Vérifiez toujours les erreurs lorsque la fiabilité est importante :

const { entries: posts, error } = await getEmDashCollection("posts");
if (error) {
// Journaliser et gérer gracieusement
console.error("Échec du chargement des articles :", error);
return new Response("Erreur serveur", { status: 500 });
}

Utilisez getEmDashEntry pour récupérer une entrée par son ID ou son slug :

astro title="src/pages/posts/[slug].astro"
---
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("Server error", { status: 500 });
}
if (!post) {
return Astro.redirect("/404");
}
---
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>

getEmDashEntry retourne un objet résultat :

interface EntryResult<T> {
entry: ContentEntry<T> | null; // null if not found
error?: Error; // Only set for actual errors (not "not found")
isPreview: boolean; // true if viewing preview/draft content
}
interface ContentEntry<T> {
id: string;
data: T;
edit: EditProxy; // Visual editing annotations
}

L’objet data dans entry contient tous les champs définis pour le type de contenu. Le proxy edit fournit des annotations d’édition visuelle (voir ci-dessous).

EmDash gère la prévisualisation automatiquement via un middleware. Lorsqu’une URL contient un jeton _preview valide, le middleware le vérifie et configure le contexte de la requête. Vos fonctions de requête servent alors le contenu en brouillon sans paramètres spéciaux :

astro title="src/pages/posts/[...slug].astro"
---
import { getEmDashEntry } from "emdash";
const { slug } = Astro.params;
// Aucune gestion spéciale de prévisualisation nécessaire — le middleware le fait automatiquement
const { entry, isPreview, error } = await getEmDashEntry("posts", slug);
if (error) {
return new Response("Server error", { status: 500 });
}
if (!entry) {
return Astro.redirect("/404");
}
---
{isPreview && (
<div class="preview-banner">
Viewing preview. This content is not published.
</div>
)}
<article>
<h1>{entry.data.title}</h1>
<PortableText value={entry.data.content} />
</article>

Chaque entrée retournée par les fonctions de requête inclut un proxy edit pour annoter vos modèles. Étalez-le sur les éléments pour activer l’édition en ligne pour les éditeurs authentifiés :

<article {...entry.edit}>
<h1 {...entry.edit.title}>{entry.data.title}</h1>
<div {...entry.edit.content}>
<PortableText value={entry.data.content} />
</div>
</article>

En mode édition, {...entry.edit.title} produit un attribut data-emdash-ref que la barre d’outils d’édition visuelle utilise pour activer l’édition en ligne. En production, les étalements de proxy ne produisent aucune sortie — coût d’exécution nul.

getEmDashCollection ne garantit pas l’ordre de tri. Triez les résultats dans votre modèle :

const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
// Trier par date de publication, la plus récente d'abord
const sorted = posts.sort(
(a, b) => (b.data.publishedAt?.getTime() ?? 0) - (a.data.publishedAt?.getTime() ?? 0),
);
// Alphabetical by title
posts.sort((a, b) => a.data.title.localeCompare(b.data.title));
// Par champ d'ordre personnalisé
posts.sort((a, b) => (a.data.order ?? 0) - (b.data.order ?? 0));
// Ordre aléatoire
posts.sort(() => Math.random() - 0.5);

Générez des types TypeScript pour vos collections :

Fenêtre de terminal
npx emdash types

Cela crée .emdash/types.ts avec des interfaces pour chaque collection. Utilisez-les pour la sécurité des types :

import { getEmDashCollection, getEmDashEntry } from "emdash";
import type { Post } from "../../.emdash/types";
// Requête de collection typée
const { entries: posts } = await getEmDashCollection<Post>("posts");
// posts est ContentEntry<Post>[]
// Requête d'entrée typée
const { entry: post } = await getEmDashEntry<Post>("posts", "my-post");
// post est ContentEntry<Post> | null

Le contenu EmDash fonctionne avec les pages statiques et rendues côté serveur.

Pour les pages statiques, utilisez getStaticPaths pour générer les routes au moment de la construction :

astro title="src/pages/posts/[slug].astro"
---
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);
---

Pour les pages rendues côté serveur, interrogez le contenu directement :

astro title="src/pages/posts/[slug].astro"
---
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("Erreur serveur", { status: 500 });
}
if (!post) {
return new Response(null, { status: 404 });
}
---

EmDash utilise les collections de contenu en direct d’Astro, qui gèrent automatiquement la mise en cache. Pour les pages rendues côté serveur, envisagez d’ajouter des en-têtes de cache HTTP :

---
const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
// Cache pendant 5 minutes
Astro.response.headers.set("Cache-Control", "public, max-age=300");
---

Effectuez la requête une fois et transmettez les données aux composants :

astro title="src/pages/index.astro"
---
import { getEmDashCollection } from "emdash";
import PostList from "../../components/PostList.astro";
import Sidebar from "../../components/Sidebar.astro";
// Requête unique
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} />