From 57e5e2ee31003971270fceb37d883ea97e610545 Mon Sep 17 00:00:00 2001 From: Alejandro de la Fuente Date: Wed, 17 Jun 2026 23:02:28 +0200 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20filtro=20de=20art=C3=ADculos=20por?= =?UTF-8?q?=20tag=20con=20p=C3=A1ginas=20dedicadas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Nueva ruta /ensayos/tags/[tag] con página dedicada por cada tag (35 tags) - Tag cloud en /ensayos con todos los tags ordenados por frecuencia - Tags clicables en índice y detalle de artículo - Estilos: hover state, active state, tag cloud layout --- src/pages/ensayos/[...slug].astro | 2 +- src/pages/ensayos/index.astro | 24 +++++++++- src/pages/ensayos/tags/[tag].astro | 72 ++++++++++++++++++++++++++++++ src/styles/site.css | 37 +++++++++++++++ 4 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 src/pages/ensayos/tags/[tag].astro diff --git a/src/pages/ensayos/[...slug].astro b/src/pages/ensayos/[...slug].astro index d14bfab..d5a9a22 100644 --- a/src/pages/ensayos/[...slug].astro +++ b/src/pages/ensayos/[...slug].astro @@ -22,7 +22,7 @@ const fmtFecha = (d: Date) =>

{post.data.title}

{post.data.autor}

- {post.data.tags.map((tag) => {tag})} + {post.data.tags.map((tag) => {tag})}

diff --git a/src/pages/ensayos/index.astro b/src/pages/ensayos/index.astro index 1e791e3..53ce538 100644 --- a/src/pages/ensayos/index.astro +++ b/src/pages/ensayos/index.astro @@ -8,6 +8,15 @@ const ensayos = (await getCollection('ensayos')).sort( const fmtFecha = (d: Date) => d.toLocaleDateString('es-ES', { year: 'numeric', month: 'short', day: '2-digit' }); + +// Build tag counts, sorted by frequency +const tagCounts = new Map(); +for (const post of ensayos) { + for (const tag of post.data.tags) { + tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1); + } +} +const sortedTags = Array.from(tagCounts.entries()).sort((a, b) => b[1] - a[1]); --- Claims fuertes con evidencia al lado. Lo que aprendemos construyendo en público, escrito para que te sirva.

-
    + + + + +
      { ensayos.map((post) => (
    • @@ -36,7 +56,7 @@ const fmtFecha = (d: Date) =>

      {post.data.description}

      {post.data.tags.slice(0, 4).map((tag) => ( - {tag} + {tag} ))}

    • diff --git a/src/pages/ensayos/tags/[tag].astro b/src/pages/ensayos/tags/[tag].astro new file mode 100644 index 0000000..ee71c55 --- /dev/null +++ b/src/pages/ensayos/tags/[tag].astro @@ -0,0 +1,72 @@ +--- +import Base from '../../../layouts/Base.astro'; +import { getCollection } from 'astro:content'; + +export async function getStaticPaths() { + const ensayos = await getCollection('ensayos'); + const allTags = new Set(); + for (const post of ensayos) { + for (const tag of post.data.tags) { + allTags.add(tag); + } + } + return Array.from(allTags).map((tag) => ({ params: { tag }, props: { tag } })); +} + +const { tag } = Astro.props; + +const ensayos = (await getCollection('ensayos')) + .filter((p) => p.data.tags.includes(tag)) + .sort((a, b) => b.data.fecha.valueOf() - a.data.fecha.valueOf()); + +const fmtFecha = (d: Date) => + d.toLocaleDateString('es-ES', { year: 'numeric', month: 'short', day: '2-digit' }); +--- + + +
      +
      +

      artículos

      +

      Artículos sobre «{tag}»

      +

      + {ensayos.length} artículo{ensayos.length !== 1 ? 's' : ''} etiquetado{ensayos.length !== 1 ? 's' : ''} con {tag}. + ← Ver todos +

      + { + ensayos.length === 0 ? ( +

      + No hay artículos con este tag todavía. +

      + ) : ( +
        + {ensayos.map((post) => ( +
      • +

        + {fmtFecha(post.data.fecha)} · {post.data.autor} +

        +

        + {post.data.title} +

        +

        {post.data.description}

        +

        + {post.data.tags.map((t) => ( + + {t} + + ))} +

        +
      • + ))} +
      + ) + } +
      +
      + diff --git a/src/styles/site.css b/src/styles/site.css index 9575189..4313602 100644 --- a/src/styles/site.css +++ b/src/styles/site.css @@ -131,6 +131,43 @@ a.card:hover { border: 1px solid var(--color-borde); color: var(--color-tinta3); margin-right: 0.4rem; + margin-bottom: 0.35rem; + text-decoration: none; + transition: border-color var(--transition-fast), color var(--transition-fast), + background var(--transition-fast); +} + +a.tag:hover { + text-decoration: none; + border-color: var(--color-cielo); + color: var(--color-cielo); + background: var(--color-accent-soft); +} + +.tag--active { + border-color: var(--color-cielo); + color: var(--color-cielo); + background: var(--color-accent-soft); +} + +.tag sup { + font-size: 0.65em; + color: var(--color-tinta3); + margin-left: 0.15em; + vertical-align: super; +} + +/* tag cloud / filter bar */ +.tag-cloud { + display: flex; + flex-wrap: wrap; + gap: 0.25rem; + align-items: center; +} + +.tag-cloud .tag { + font-size: 0.72rem; + padding: 0.2rem 0.7rem; } .badge { From 68ade75da0c78c36c6c7d378d2114e4220bd5f86 Mon Sep 17 00:00:00 2001 From: Alejandro de la Fuente Date: Wed, 17 Jun 2026 23:29:23 +0200 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20a=C3=B1ade=20buscador=20full-text?= =?UTF-8?q?=20con=20Pagefind=20+=20filtro=20de=20tags=20en=20cliente?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pagefind indexa 14 ensayos (3344 palabras) post-build - Buscador en /ensayos: busca por título, tags y contenido - Tag cloud con filtrado en cliente: clic en un tag oculta/muestra artículos sin recargar - Tags clicables en artículos aplican el filtro al instante - URL se actualiza con pushState para compartir filtros - data-pagefind-meta/body en páginas de ensayo para indexación precisa - Estilos dark theme para el UI de Pagefind --- package.json | 5 +- pnpm-lock.yaml | 75 +++++++++++ src/pages/ensayos/[...slug].astro | 8 +- src/pages/ensayos/index.astro | 202 ++++++++++++++++++++++++++++-- src/styles/site.css | 11 +- 5 files changed, 287 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index d551a29..0b8bcf7 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "packageManager": "pnpm@11.5.2", "scripts": { "dev": "astro dev", - "build": "astro build", + "build": "astro build && pagefind --site dist", "preview": "astro preview", "migrate:blog": "node scripts/migrate-blog.mjs" }, @@ -23,5 +23,8 @@ "repository": { "type": "git", "url": "https://github.com/codigosinsiesta/codigosinsiesta.github.io" + }, + "devDependencies": { + "pagefind": "^1.5.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 21c8670..a2f5816 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,10 @@ importers: svelte: specifier: ^5.45.5 version: 5.56.3 + devDependencies: + pagefind: + specifier: ^1.5.2 + version: 1.5.2 packages: @@ -580,6 +584,41 @@ packages: '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + '@pagefind/darwin-arm64@1.5.2': + resolution: {integrity: sha512-MXpI+7HsAdPkvJ0gk9xj9g541BCqBZOBbdwj9g6lB5LCj6kSV6nqDSjzcAJwvOsfu0fjwvC8hQU+ecfhp+MpiQ==} + cpu: [arm64] + os: [darwin] + + '@pagefind/darwin-x64@1.5.2': + resolution: {integrity: sha512-IojxFWMEJe0RQ7PQ3KXQsPIImNsbpPYpoZ+QUDrL8fAl/O27IX+LVLs74/UzEZy5uA2LD8Nz1AiwKr72vrkZQw==} + cpu: [x64] + os: [darwin] + + '@pagefind/freebsd-x64@1.5.2': + resolution: {integrity: sha512-7EVzo9+0w+2cbe671BtMj10UlNo83I+HrLVLfRxO731svHRJKUfJ/mo05gU14pe9PCfpKNQT8FS3Xc/oDN6pOA==} + cpu: [x64] + os: [freebsd] + + '@pagefind/linux-arm64@1.5.2': + resolution: {integrity: sha512-Ovt9+K35sqzn8H3ZMXGwls4TD/wMJuvRtShHIsmUQREmaxjrDEX7gHckRCrwYJ4XE1H1p6HkLz3wukrAnsfXQw==} + cpu: [arm64] + os: [linux] + + '@pagefind/linux-x64@1.5.2': + resolution: {integrity: sha512-V+tFqHKXhQKq/WqPBD67AFy7scn1/aZID00ws4fSDd+1daSi5UHR9VVlRrOUYKxn3VuFQYRD7lYXdZK1WED1YA==} + cpu: [x64] + os: [linux] + + '@pagefind/windows-arm64@1.5.2': + resolution: {integrity: sha512-hN9Nh90fNW61nNRCW9ZyQrAj/mD0eRvmJ8NlTUzkbuW8kIzGJUi3cxjFkEcMZ5h/8FsKWD/VcouZl4yo1F7B6g==} + cpu: [arm64] + os: [win32] + + '@pagefind/windows-x64@1.5.2': + resolution: {integrity: sha512-Fa2Iyw7kaDRzGMfNYNUXNW2zbL5FQVDgSOcbDHdzBrDEdpqOqg8TcZ68F22ol6NJ9IGzvUdmeyZypLW5dyhqsg==} + cpu: [x64] + os: [win32] + '@rollup/pluginutils@5.4.0': resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==} engines: {node: '>=14.0.0'} @@ -1399,6 +1438,10 @@ packages: package-manager-detector@1.6.0: resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} + pagefind@1.5.2: + resolution: {integrity: sha512-XTUaK0hXMCu2jszWE584JGQT7y284TmMV9l/HX3rnG5uo3rHI/uHU56XTyyyPFjeWEBxECbAi0CaFDJOONtG0Q==} + hasBin: true + parse-latin@7.0.0: resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} @@ -1597,6 +1640,7 @@ packages: tsconfck@3.1.6: resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} engines: {node: ^18 || >=20} + deprecated: unmaintained hasBin: true peerDependencies: typescript: ^5.0.0 @@ -2225,6 +2269,27 @@ snapshots: '@oslojs/encoding@1.1.0': {} + '@pagefind/darwin-arm64@1.5.2': + optional: true + + '@pagefind/darwin-x64@1.5.2': + optional: true + + '@pagefind/freebsd-x64@1.5.2': + optional: true + + '@pagefind/linux-arm64@1.5.2': + optional: true + + '@pagefind/linux-x64@1.5.2': + optional: true + + '@pagefind/windows-arm64@1.5.2': + optional: true + + '@pagefind/windows-x64@1.5.2': + optional: true + '@rollup/pluginutils@5.4.0(rollup@4.61.1)': dependencies: '@types/estree': 1.0.9 @@ -3307,6 +3372,16 @@ snapshots: package-manager-detector@1.6.0: {} + pagefind@1.5.2: + optionalDependencies: + '@pagefind/darwin-arm64': 1.5.2 + '@pagefind/darwin-x64': 1.5.2 + '@pagefind/freebsd-x64': 1.5.2 + '@pagefind/linux-arm64': 1.5.2 + '@pagefind/linux-x64': 1.5.2 + '@pagefind/windows-arm64': 1.5.2 + '@pagefind/windows-x64': 1.5.2 + parse-latin@7.0.0: dependencies: '@types/nlcst': 2.0.3 diff --git a/src/pages/ensayos/[...slug].astro b/src/pages/ensayos/[...slug].astro index d5a9a22..6d217ee 100644 --- a/src/pages/ensayos/[...slug].astro +++ b/src/pages/ensayos/[...slug].astro @@ -19,13 +19,13 @@ const fmtFecha = (d: Date) =>

      ensayo · {fmtFecha(post.data.fecha)}

      -

      {post.data.title}

      -

      {post.data.autor}

      -

      +

      {post.data.title}

      +

      {post.data.autor}

      +

      {post.data.tags.map((tag) => {tag})}

      -
      +