Ir al contenido

Consultar contenido

EmDash proporciona funciones de consulta para recuperar contenido en tus páginas y componentes de Astro. Estas funciones siguen el patrón de colecciones de contenido en vivo de Astro, devolviendo resultados estructurados con manejo de errores.

EmDash exporta dos funciones de consulta principales:

FunciónPropósitoDevuelve
getEmDashCollectionRecuperar todas las entradas de un tipo de contenido{ entries, error }
getEmDashEntryRecuperar una sola entrada por ID o slug{ entry, error, isPreview }

Impórtalas desde emdash:

import { getEmDashCollection, getEmDashEntry } from "emdash";

Usa getEmDashCollection para recuperar todas las entradas de un tipo de contenido:

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

Cuando la i18n está habilitada, filtra por idioma para recuperar contenido en un idioma específico:

// Entradas en francés
const { entries: frenchPosts } = await getEmDashCollection("posts", {
locale: "fr",
status: "published",
});
// Usa el idioma actual de la solicitud
const { entries: localizedPosts } = await getEmDashCollection("posts", {
locale: Astro.currentLocale,
status: "published",
});

Para entradas individuales, pasa locale como tercer argumento:

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

Cuando se omite locale, por defecto se usa el idioma actual de la solicitud. Si no existe una traducción para el idioma solicitado, se sigue la cadena de respaldo.

Recupera solo contenido publicado o borrador:

// Solo entradas publicadas
const { entries: published } = await getEmDashCollection("posts", {
status: "published",
});
// Solo borradores
const { entries: drafts } = await getEmDashCollection("posts", {
status: "draft",
});

Restringe el número de entradas devueltas:

// Obtener las 5 entradas más recientes
const { entries: recentPosts } = await getEmDashCollection("posts", {
status: "published",
limit: 5,
});

Filtra entradas por categoría, etiqueta o términos de taxonomía personalizados:

// Entradas de la categoría "news"
const { entries: newsPosts } = await getEmDashCollection("posts", {
status: "published",
where: { category: "news" },
});
// Publicaciones con la etiqueta "javascript"
const { entries: jsPosts } = await getEmDashCollection("posts", {
status: "published",
where: { tag: "javascript" },
});
// Publicaciones que coinciden con cualquiera de múltiples términos
const { entries: featuredNews } = await getEmDashCollection("posts", {
status: "published",
where: { category: ["news", "featured"] },
});

El filtro where usa lógica OR cuando se proporcionan múltiples valores para una sola taxonomía.

Siempre verifica si hay errores cuando la fiabilidad es importante:

const { entries: posts, error } = await getEmDashCollection("posts");
if (error) {
// Registrar y manejar con gracia
console.error("Error al cargar las publicaciones:", error);
return new Response("Error del servidor", { status: 500 });
}

Usa getEmDashEntry para recuperar una entrada por su ID o slug:

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("Error del servidor", { status: 500 });
}
if (!post) {
return Astro.redirect("/404");
}
---
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>

getEmDashEntry devuelve un objeto de resultado:

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
}

El objeto data dentro de entry contiene todos los campos definidos para el tipo de contenido. El proxy edit proporciona anotaciones para edición visual (ver más abajo).

EmDash maneja la vista previa automáticamente a través de middleware. Cuando una URL contiene un token _preview válido, el middleware lo verifica y configura el contexto de la solicitud. Tus funciones de consulta luego sirven contenido en borrador sin ningún parámetro especial:

src/pages/posts/[...slug].astro
---
import { getEmDashEntry } from "emdash";
const { slug } = Astro.params;
// No se necesita manejo especial de vista previa — el middleware lo hace automáticamente
const { entry, isPreview, error } = await getEmDashEntry("posts", slug);
if (error) {
return new Response("Error del servidor", { status: 500 });
}
if (!entry) {
return Astro.redirect("/404");
}
---
{isPreview && (
<div class="preview-banner">
Estás viendo una vista previa. Este contenido aún no está publicado.
</div>
)}
<article>
<h1>{entry.data.title}</h1>
<PortableText value={entry.data.content} />
</article>

Cada entrada devuelta por las funciones de consulta incluye un proxy edit para anotar tus plantillas. Extiéndelo en los elementos para habilitar la edición en línea para editores autenticados:

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

En modo de edición, {...entry.edit.title} produce un atributo data-emdash-ref que la barra de herramientas de edición visual usa para habilitar la edición en línea. En producción, la extensión del proxy no produce salida — costo de ejecución cero.

getEmDashCollection no garantiza un orden. Ordena los resultados en tu plantilla:

const { entries: posts } = await getEmDashCollection("posts", {
status: "published",
});
// Ordenar por fecha de publicación, los más nuevos primero
const sorted = posts.sort(
(a, b) => (b.data.publishedAt?.getTime() ?? 0) - (a.data.publishedAt?.getTime() ?? 0),
);
// Orden alfabético por título
posts.sort((a, b) => a.data.title.localeCompare(b.data.title));
// Por campo de orden personalizado
posts.sort((a, b) => (a.data.order ?? 0) - (b.data.order ?? 0));
// Orden aleatorio
posts.sort(() => Math.random() - 0.5);

Genera tipos de TypeScript para tus colecciones:

Ventana de terminal
npx emdash types

Esto crea .emdash/types.ts con interfaces para cada colección. Úsalas para seguridad de tipos:

import { getEmDashCollection, getEmDashEntry } from "emdash";
import type { Post } from "../../.emdash/types";
// Consulta de colección con seguridad de tipos
const { entries: posts } = await getEmDashCollection<Post>("posts");
// posts es ContentEntry<Post>[]
// Consulta de entrada con seguridad de tipos
const { entry: post } = await getEmDashEntry<Post>("posts", "my-post");
// post es ContentEntry<Post> | null

El contenido de EmDash funciona tanto con páginas estáticas como renderizadas en el servidor.

Para páginas estáticas, usa getStaticPaths para generar rutas en tiempo de compilación:

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);
---

Para páginas renderizadas en el servidor, consulta el contenido directamente:

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("Error del servidor", { status: 500 });
}
if (!post) {
return new Response(null, { status: 404 });
}
---

EmDash utiliza las colecciones de contenido en vivo de Astro, que manejan el almacenamiento en caché automáticamente. Para páginas renderizadas en el servidor, considera agregar encabezados de caché HTTP:

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

Consulta una vez y pasa los datos a los componentes:

src/pages/index.astro
---
import { getEmDashCollection } from "emdash";
import PostList from "../../components/PostList.astro";
import Sidebar from "../../components/Sidebar.astro";
// Consultar una vez
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} />