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().replace(':', '') } 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 = await this.site() const request = await fetch('assets/templates/results.html') const template = await request.text() 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 } async site () { if (!window.site) { const data = await fetch('assets/data/site.json') window.site = await data.json() } return window.site } }