[🛠] Igualar los resultados de búsqueda a las tarjetas del listado
✨ Resumen de GPT-5.5
Registro de cómo reemplacé las tarjetas de búsqueda armadas con cadenas de JavaScript por una tarjeta Liquid compartida, para que fecha, categorías, vistas y layout del overlay sigan las mismas reglas que los listados normales.
Los resultados de búsqueda se veían viejos.
En la portada y en las páginas de categorías, las tarjetas de posts ya tenían una forma más ordenada. Debajo del título aparecían la fecha, las categorías y el contador de vistas en la misma fila de metadatos.
Pero al abrir la búsqueda aparecía otra UI antigua.
Mostraba solo título y extracto. No se veía de inmediato cuándo se había escrito el post. Tampoco había categoría ni vistas. El mismo post tenía contexto en los listados normales, pero lo perdía en la búsqueda.
La causa era que los resultados de búsqueda todavía se renderizaban con una cadena HTML construida aparte en JavaScript.
El renderizado con cadenas JavaScript envejecía la búsqueda
Lunr sigue encargado de buscar.
En un blog estático con Jekyll, tiene sentido crear un store de búsqueda durante el build y consultarlo desde JavaScript en el navegador.
El problema era que JavaScript también construía la tarjeta del resultado.
Los listados normales los renderizaba _includes/archive-single.html, mientras que los resultados de búsqueda se armaban como cadenas en assets/js/lunr/lunr-en.js.
La estructura era más o menos esta:
Regular listing
-> Liquid include
-> archive__item
-> date, category, views
Search results
-> Lunr JS
-> hand-built HTML string
-> title and excerpt only
Ese era el fallo.
Si agregaba badges de categoría al listado normal, la búsqueda no cambiaba. Si cambiaba la regla de fecha, la búsqueda no cambiaba. Si ajustaba las vistas, la búsqueda seguía igual.
La misma tarjeta se mantenía en dos lugares.
Separé la tarjeta de post en un include compartido
En vez de agrandar el JavaScript de búsqueda, hice que generara menos HTML.
Creé includes compartidos para la tarjeta.
_includes/archive-item-card.html
_includes/archive-item-meta-row.html
_includes/archive-item-categories.html
archive-item-card.html recibe un documento y renderiza la misma estructura que usan los listados de archivo.
list__item
archive__item
archive__item-title
archive__item-meta-row
archive__item-excerpt
archive-item-meta-row.html agrupa fecha, vistas y categorías en una línea. La fecha y las vistas siguen usando page__meta.html; las categorías pasan por archive-item-categories.html.
Después _includes/archive-single.html quedó como un wrapper fino.
{% include archive-item-card.html document=post type=include.type context="archive" %}
Ahora los listados normales y los resultados de búsqueda usan el HTML generado por el mismo include.
Guardé el HTML completo de la tarjeta en el store de Lunr
Lunr sigue haciendo la búsqueda.
Pero JavaScript ya no construye el HTML de la tarjeta.
Durante el build de Jekyll, assets/js/lunr/lunr-store.js renderiza el include de tarjeta para cada documento y guarda el resultado en el campo html.
title
excerpt
categories
tags
lang
locale
html
url
teaser
El JavaScript de búsqueda ahora solo toma entry.html y lo inserta.
Antes mezclaba enlaces de título, imagen teaser, recorte de extracto y armado de strings HTML.
var renderSearchResult = function (entry) {
return entry.html || '';
};
Lo que queda en el JS de búsqueda es buscar, filtrar por locale, mostrar el conteo e insertar resultados.
Las vistas en resultados se muestran, no se registran
Había que decidir si la búsqueda debía mostrar vistas.
Al principio pensé en quitarlas. Podían meter ruido, y además había que resolver el timing para DOM insertado dinámicamente.
Pero si la tarjeta debía coincidir con el listado normal, dejar fuera solo las vistas también era raro.
Así que las vistas se muestran en búsqueda. Lo que separé fue visualización y registro.
Search result exposure is not a visit.
The view count in search results is display-only.
Actual visit tracking belongs only to the currently opened page.
Los elementos de vistas del blog tienen data-page-view-path. El elemento que realmente registra la visita es el de la página actual con data-page-view-track="true".
Las tarjetas de búsqueda solo tienen data-page-view-path; no tienen data-page-view-track="true".
Entonces aparecer en resultados de búsqueda no incrementa las vistas del post.
Solo muestra el número.
Reapliqué vistas a resultados insertados dinámicamente
Los resultados de búsqueda no existen en el DOM al cargar la página.
Se insertan cuando el usuario escribe una consulta. Si el script de vistas recoge elementos solo una vez al cargar, las vistas dentro de resultados de búsqueda no se llenan.
Por eso también cambié assets/js/custom/visitor-stats.js.
En vez de fijar document.querySelectorAll("[data-page-view-path]") al inicio, ahora vuelve a buscar esos elementos cada vez que renderiza vistas.
También cacheé el payload de analytics.
latestAnalyticsPayload
Cuando se renderizan resultados, el script de búsqueda emite hyuk:search-results-rendered.
El script de visitor stats escucha ese evento y, si ya tiene payload, reaplica vistas al DOM nuevo.
No vuelve a llamar a la API.
Si cada cambio de input hiciera una llamada de vistas, la búsqueda interferiría con el sistema de contador. Los resultados cambian mucho, así que las requests no deben crecer con cada tecla.
El flujo queda así:
Page load
-> receive analytics payload once
-> render views for existing listing/current page
Search results render
-> dispatch event
-> reuse cached payload for newly inserted DOM
Así los resultados de búsqueda no contaminan el contador.
Alineé los metadatos multilingües por locale
Después del trabajo multilingüe del blog, el sitio tiene páginas y collections por locale como /en/, /ja/ y /zh-Hans/. La búsqueda no puede mezclar locales.
El store de búsqueda incluye lang y locale, y el HTML de la tarjeta usa el locale del documento para sus etiquetas. En inglés aparece Views, en japonés 閲覧数, y en español Vistas.
Las categorías siguen la misma regla.
El prefijo de locale no debe aparecer como badge de categoría, así que archive-item-categories.html omite ese segmento y muestra solo las categorías reales.
Restauré la sidebar y un ancho mayor en el overlay de búsqueda
Igualar la tarjeta no bastaba.
Al abrir búsqueda, el ancho de resultados seguía siendo demasiado estrecho. Aunque usaba el mismo HTML de tarjeta que los listados normales, no aprovechaba el espacio disponible a la derecha.
También había un problema mayor: al abrir búsqueda desaparecían las categorías laterales.
El overlay de búsqueda no se superpone al cuerpo existente. Al abrirlo, .initial-content se oculta y se muestra un área separada #site-search.
Eso significa que la sidebar de la página normal también desaparece. Aunque la tarjeta sea compartida, la pantalla de búsqueda sigue pareciendo otra si el layout exterior cambia.
Por eso incluí la sidebar dentro de _includes/search/search_form.html.
<div class="search-content__inner-wrap">
{% include sidebar.html %}
<div class="archive search-content__archive">
...
</div>
</div>
También envolví los resultados con archive search-content__archive para que fluyeran dentro del layout de archivo.
Luego quité la regla CSS que estrechaba las tarjetas.
Minimal Mistakes tenía esta regla para búsqueda.
.search-content .archive__item {
@include breakpoint($large) {
width: 75%;
}
@include breakpoint($x-large) {
width: 50%;
}
}
La búsqueda no se veía antigua solo por el HTML. En pantallas grandes, la tarjeta se reducía hasta la mitad.
En SCSS personalizado hice que las tarjetas de búsqueda usaran todo el ancho.
.search-content .archive__item {
width: 100%;
}
Quedaba otro detalle.
El archive normal reserva espacio derecho con padding-inline-end para la sidebar derecha. El overlay de búsqueda no tiene esa sidebar. Si se mantiene ese padding, los resultados vuelven a quedar estrechos.
Así que quité ese padding solo para el archive del overlay.
.search-content .search-content__archive {
padding-inline-end: 0;
}
Las reglas de renderizado de la tarjeta se comparten con el listado normal; el layout del overlay se ajusta para la pantalla de búsqueda.
Revisé escritorio y móvil
Ejecuté build y checks de sintaxis.
bundle exec jekyll build
node --check _site/assets/js/lunr/lunr-store.js
node --check _site/assets/js/lunr/lunr-en.js
node --check _site/assets/js/custom/visitor-stats.js
El store generado incluye page__views y data-page-view-path.
El HTML de tarjeta de búsqueda no incluye data-page-view-track="true", para no mezclar aparición en búsqueda con registro de visita.
Luego abrí la búsqueda en páginas de varios locales y probé consultas como:
References
Keymory
Daily review
Las tarjetas mostraron fecha, categoría y vistas en la misma fila de metadatos que los listados normales. Las etiquetas siguieron cada locale: Views, 閲覧数, Vistas y las demás.
Dentro de los resultados no apareció data-page-view-track="true". En las páginas de posts, el elemento de tracking de la página actual siguió apareciendo una sola vez.
El overlay de búsqueda volvió a tener sidebar. En escritorio de 1280px, la sidebar tenía 22 elementos y la tarjeta de resultado llegó a unos 974px de ancho.
En móvil de 390px, la sidebar se apiló arriba y la tarjeta usó 345px para título, metadatos y extracto.
No hubo errores en la consola del navegador.
Deja un comentario