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

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 administración

  1. Ve a la página de taxonomía (ej. /_emdash/admin/taxonomies/category)
  2. Ingresa el nombre del término en el formulario Agregar nuevo
  3. Opcionalmente configura:
    • Slug - Identificador URL (generado automáticamente del nombre)
    • Padre - Para taxonomías jerárquicas
    • Descripción - Descripción del término
  4. Haz clic en Agregar

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 para los términos aplicables, o haz clic en + Agregar nuevo
  4. Para etiquetas, escribe nombres de etiquetas separados por comas
  5. Guarda el contenido

API

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 y tutoriales prácticos"
}

Editar un término

  1. Ve a la página de términos de 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 taxonomía
  2. Haz clic en Eliminar junto al término
  3. Confirma la eliminación

Consultar taxonomías

Obtener todos los términos

import { getTaxonomyTerms } from "emdash";

const categories = await getTaxonomyTerms("category");
const tags = await getTaxonomyTerms("tag");
interface TaxonomyTerm {
	id: string;
	name: string;
	slug: string;
	label: string;
	parentId?: string;
	description?: string;
	children: TaxonomyTerm[];
	count?: number;
}

Si solo necesitas etiquetas y slugs, omite el cálculo de conteo:

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

Obtener un solo término

import { getTerm } from "emdash";

const category = await getTerm("category", "news");
const category = await getTerm("category", "news", { includeCounts: false });

Obtener términos de una entrada

import { getEntryTerms } from "emdash";

const categories = await getEntryTerms("posts", "post-123", "category");
const tags = await getEntryTerms("posts", "post-123", "tag");

Filtrar contenido por término

import { getEmDashCollection } from "emdash";

const { entries: newsPosts } = await getEmDashCollection("posts", {
	status: "published",
	where: { category: "news" },
});

O usa la función de conveniencia:

import { getEntriesByTerm } from "emdash";
const newsPosts = await getEntriesByTerm("posts", "category", "news");

Construir páginas de taxonomía

Archivo de categorías

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

export async function getStaticPaths() {
  const categories = await getTaxonomyTerms("category");
  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 etiquetas

---
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 etiquetados "${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

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

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

const tags = await getTaxonomyTerms("tag");
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

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

Crear una taxonomía personalizada

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

import { getTaxonomyTerms, getEmDashCollection } from "emdash";

const genres = await getTaxonomyTerms("genre");
const { entries: sciFiBooks } = await getEmDashCollection("books", {
	where: { genre: "science-fiction" },
});

Referencia de API de taxonomía

EndpointMétodoDescripción
/_emdash/api/taxonomiesGETListar definiciones
/_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

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