Taxonomías

En esta página

Las taxonomías son sistemas de clasificación para organizar contenido. EmDash incluye categorías y etiquetas integradas, y soporta taxonomías personalizadas para necesidades de clasificación especializadas.

Taxonomías integradas

EmDash proporciona dos taxonomías predeterminadas:

TaxonomíaTipoDescripción
CategoríasJerárquicaClasificación anidada con relaciones padre-hijo
EtiquetasPlanaEtiquetas simples sin jerarquía

Ambas están disponibles para la colección de posts por defecto.

Gestionar términos

Crear un término

Panel de admin

  1. Ve a la página de taxonomía (ej. /_emdash/admin/taxonomies/category)

  2. Introduce el nombre del término en el formulario Añadir nuevo

  3. Opcionalmente configura:

    • Slug - Identificador de URL (generado automáticamente del nombre)
    • Padre - Para taxonomías jerárquicas
    • Descripción - Descripción del término
  4. Haz clic en Añadir

Editor de contenido

  1. Abre una entrada de contenido en el editor

  2. Encuentra el panel de taxonomía en la barra lateral

  3. Para categorías, marca las casillas de los términos aplicables, o haz clic en + Añadir nuevo

  4. Para etiquetas, escribe nombres de etiquetas separados por comas

  5. Guarda el contenido

API

La siguiente solicitud crea un término en la taxonomía category:

POST /_emdash/api/taxonomies/category/terms
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

{
  "slug": "tutorials",
  "label": "Tutoriales",
  "parentId": "term_abc",
  "description": "Guías prácticas y tutoriales"
}

Editar un término

  1. Ve a la página de términos de la taxonomía

  2. Haz clic en Editar junto al término

  3. Actualiza el nombre, slug, padre o descripción

  4. Haz clic en Guardar

Eliminar un término

  1. Ve a la página de términos de la taxonomía

  2. Haz clic en Eliminar junto al término

  3. Confirma la eliminación

Consultar taxonomías

EmDash proporciona funciones para consultar términos de taxonomía y filtrar contenido por término.

Obtener todos los términos

Recupera todos los términos de una taxonomía:

import { getTaxonomyTerms } from "emdash";

// Obtener todas las categorías (retorna estructura de árbol)
const categories = await getTaxonomyTerms("category");

// Obtener todas las etiquetas (retorna lista plana)
const tags = await getTaxonomyTerms("tag");

Para taxonomías jerárquicas, los términos incluyen un array children:

interface TaxonomyTerm {
	id: string;
	name: string; // Nombre de taxonomía ("category")
	slug: string; // Slug del término ("news")
	label: string; // Etiqueta de visualización ("News")
	parentId?: string;
	description?: string;
	children: TaxonomyTerm[];
	count?: number; // Número de entradas con este término
}

Calcular count agrega cada asignación contenido-término en las colecciones de la taxonomía, lo cual es la parte más costosa de la llamada. Si solo necesitas etiquetas y slugs, omítelo — count se excluye entonces de los términos retornados:

const tags = await getTaxonomyTerms("tag", { includeCounts: false });

Obtener un solo término

El siguiente ejemplo obtiene un término por taxonomía y slug:

import { getTerm } from "emdash";

const category = await getTerm("category", "news");
// Retorna TaxonomyTerm o null

Obtener términos de una entrada

El siguiente ejemplo recupera las categorías y etiquetas asignadas a una sola entrada:

import { getEntryTerms } from "emdash";

// Obtener todas las categorías de un post
const categories = await getEntryTerms("posts", "post-123", "category");

// Obtener todas las etiquetas de un post
const tags = await getEntryTerms("posts", "post-123", "tag");

Filtrar contenido por término

Usa getEmDashCollection con el filtro where:

import { getEmDashCollection } from "emdash";

// Posts en la categoría "news"
const { entries: newsPosts } = await getEmDashCollection("posts", {
	status: "published",
	where: { category: "news" },
});

// Posts con la etiqueta "javascript"
const { entries: jsPosts } = await getEmDashCollection("posts", {
	status: "published",
	where: { tag: "javascript" },
});

O usa la función de conveniencia:

import { getEntriesByTerm } from "emdash";

const newsPosts = await getEntriesByTerm("posts", "category", "news");

Crear páginas de taxonomía

Archivo de categoría

Crea una página que lista posts de una categoría:

---
import { getTaxonomyTerms, getTerm, getEmDashCollection } from "emdash";
import Base from "../../layouts/Base.astro";

export async function getStaticPaths() {
  const categories = await getTaxonomyTerms("category");

  // Aplanar árbol jerárquico para enrutamiento
  function flatten(terms) {
    return terms.flatMap((term) => [term, ...flatten(term.children)]);
  }

  return flatten(categories).map((cat) => ({
    params: { slug: cat.slug },
    props: { category: cat },
  }));
}

const { category } = Astro.props;

const { entries: posts } = await getEmDashCollection("posts", {
  status: "published",
  where: { category: category.slug },
});
---

<Base title={category.label}>
  <h1>{category.label}</h1>
  {category.description && <p>{category.description}</p>}
  <p>{category.count} publicaciones</p>

  <ul>
    {posts.map((post) => (
      <li>
        <a href={`/blog/${post.data.slug}`}>{post.data.title}</a>
      </li>
    ))}
  </ul>
</Base>

Archivo de etiqueta

Crea una página que lista posts con una etiqueta:

---
import { getTaxonomyTerms, getEmDashCollection } from "emdash";
import Base from "../../layouts/Base.astro";

export async function getStaticPaths() {
  const tags = await getTaxonomyTerms("tag");

  return tags.map((tag) => ({
    params: { slug: tag.slug },
    props: { tag },
  }));
}

const { tag } = Astro.props;

const { entries: posts } = await getEmDashCollection("posts", {
  status: "published",
  where: { tag: tag.slug },
});
---

<Base title={`Posts con etiqueta "${tag.label}"`}>
  <h1>#{tag.label}</h1>

  <ul>
    {posts.map((post) => (
      <li>
        <a href={`/blog/${post.data.slug}`}>{post.data.title}</a>
      </li>
    ))}
  </ul>
</Base>

Widget de lista de categorías

Muestra una lista de categorías con conteo de posts:

---
import { getTaxonomyTerms } from "emdash";

const categories = await getTaxonomyTerms("category");
---

<nav class="category-list">
  <h3>Categorías</h3>
  <ul>
    {categories.map((cat) => (
      <li>
        <a href={`/category/${cat.slug}`}>
          {cat.label} ({cat.count})
        </a>
        {cat.children.length > 0 && (
          <ul>
            {cat.children.map((child) => (
              <li>
                <a href={`/category/${child.slug}`}>
                  {child.label} ({child.count})
                </a>
              </li>
            ))}
          </ul>
        )}
      </li>
    ))}
  </ul>
</nav>

Nube de etiquetas

Muestra etiquetas con tamaño basado en uso:

---
import { getTaxonomyTerms } from "emdash";

const tags = await getTaxonomyTerms("tag");

// Calcular tamaños de fuente basados en conteo
const counts = tags.map((t) => t.count ?? 0);
const maxCount = Math.max(...counts, 1);
const minSize = 0.8;
const maxSize = 2;

function getSize(count: number) {
  const ratio = count / maxCount;
  return minSize + ratio * (maxSize - minSize);
}
---

<div class="tag-cloud">
  {tags.map((tag) => (
    <a
      href={`/tag/${tag.slug}`}
      style={`font-size: ${getSize(tag.count ?? 0)}rem`}
    >
      {tag.label}
    </a>
  ))}
</div>

Mostrar términos en contenido

Muestra categorías y etiquetas en un post:

---
import { getEntryTerms } from "emdash";

interface Props {
  collection: string;
  entryId: string;
}

const { collection, entryId } = Astro.props;

const categories = await getEntryTerms(collection, entryId, "category");
const tags = await getEntryTerms(collection, entryId, "tag");
---

<div class="post-terms">
  {categories.length > 0 && (
    <div class="categories">
      <span>Publicado en:</span>
      {categories.map((cat, i) => (
        <>
          {i > 0 && ", "}
          <a href={`/category/${cat.slug}`}>{cat.label}</a>
        </>
      ))}
    </div>
  )}

  {tags.length > 0 && (
    <div class="tags">
      {tags.map((tag) => (
        <a href={`/tag/${tag.slug}`} class="tag">
          #{tag.label}
        </a>
      ))}
    </div>
  )}
</div>

Taxonomías personalizadas

Crea taxonomías más allá de categorías y etiquetas para necesidades especializadas.

Crear una taxonomía personalizada

Usa la API de admin para crear una taxonomía:

POST /_emdash/api/taxonomies
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

{
  "name": "genre",
  "label": "Géneros",
  "labelSingular": "Género",
  "hierarchical": true,
  "collections": ["books", "movies"]
}

Usar taxonomías personalizadas

Consulta y muestra taxonomías personalizadas de la misma forma que las integradas:

import { getTaxonomyTerms, getEmDashCollection } from "emdash";

// Obtener todos los géneros
const genres = await getTaxonomyTerms("genre");

// Obtener libros de un género
const { entries: sciFiBooks } = await getEmDashCollection("books", {
	where: { genre: "science-fiction" },
});

Asignar a colecciones

Las taxonomías especifican a qué colecciones se aplican:

{
  "name": "difficulty",
  "label": "Niveles de dificultad",
  "hierarchical": false,
  "collections": ["recipes", "tutorials"]
}

Referencia de API de taxonomías

Endpoints REST

EndpointMétodoDescripción
/_emdash/api/taxonomiesGETListar definiciones de taxonomías
/_emdash/api/taxonomiesPOSTCrear taxonomía
/_emdash/api/taxonomies/:name/termsGETListar términos
/_emdash/api/taxonomies/:name/termsPOSTCrear término
/_emdash/api/taxonomies/:name/terms/:slugGETObtener término
/_emdash/api/taxonomies/:name/terms/:slugPUTActualizar término
/_emdash/api/taxonomies/:name/terms/:slugDELETEEliminar término

Asignar términos a contenido

La siguiente solicitud asigna términos de categoría a un post:

POST /_emdash/api/content/posts/post-123/terms/category
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

{
  "termIds": ["term_news", "term_featured"]
}

Próximos pasos