sutty-base-jekyll-theme/_packs/controllers/search_controller.js
2021-11-22 14:51:50 -03:00

106 lines
2.5 KiB
JavaScript

import { Controller } from "stimulus";
import { Liquid } from "liquidjs";
const lunr = require("lunr");
require("lunr-languages/lunr.stemmer.support")(lunr);
require("lunr-languages/lunr.es")(lunr);
export default class extends Controller {
static targets = ["q"];
get q() {
if (!this.hasQTarget) return;
if (!this.qTarget.value.trim().length === 0) return;
return this.qTarget.value.trim().replaceAll(/[:~\*\^\+\-]/gi, "");
}
connect() {
const q = new URLSearchParams(window.location.search).get("q")?.trim();
if (q) {
this.qTarget.value = q;
this.search();
}
}
async search(event) {
// Detiene el envío del formulario
if (event) {
event.preventDefault();
event.stopPropagation();
}
this.formDisable = true;
// Obtiene el término de búsqueda
const q = this.q;
// Si no hay término de búsqueda, no hay búsqueda
if (q) {
// Trae el índice de búsqueda
await this.fetch();
// Hasta que no haya índice no buscamos nada, esto evita que se
// aprete enter dos veces y se fallen cosas.
if (!window.index) return;
}
const main = document.querySelector("main");
const results = window.index
.search(q)
.map((r) => window.data.find((a) => a.id == r.ref));
const site = window.site;
const template = window.templates.results;
const html = await this.engine.parseAndRender(template, {
q,
site,
results,
});
const title = `${site.i18n.search.title} - ${q}`;
const query = new URLSearchParams({ q });
window.history.pushState({ q }, title, `?${query.toString()}`);
document.title = title;
main.innerHTML = html;
this.formDisable = false;
}
async fetch() {
// Solo permite descargar uno a la vez
if (this.fetching) return;
this.fetching = true;
let response;
// Si no existe el índice, lo descarga y procesa Lunr
if (!window.data) {
response = await fetch("data.json");
window.data = await response.json();
}
if (!window.index) {
response = await fetch("idx.json");
const idx = await response.json();
window.index = lunr.Index.load(idx);
}
// Permitir volver a ejecutar
this.fetching = false;
}
set formDisable(disable) {
this.element.elements.forEach((x) => (x.disabled = disable));
}
/*
* Liquid renderer
*
* @return Liquid
*/
get engine() {
if (!window.liquid) window.liquid = new Liquid();
return window.liquid;
}
}