Un complemento de búsqueda de texto completo en javascript puro, liviano y en el navegador para Ghost (blog)
SearchinGhost es un motor de búsqueda ligero y extensible dedicado a la plataforma de blogs Ghost. Básicamente, utiliza la API Ghost Content para cargar el contenido de su blog y la potente biblioteca FlexSearch para indexar y ejecutar consultas de búsqueda.
Todo sucede en el navegador del cliente, nos ayuda a ofrecer resultados de búsqueda increíblemente rápidos y los muestra en tiempo real a sus usuarios (también conocido como "búsqueda mientras escribe"). También nos preocupamos de minimizar las cargas de la red confiando en que el localStorage
del navegador solo envíe solicitudes cuando sea necesario.
¿Tu blog está en cirílico, chino, coreano, griego, indio o cualquier otro idioma no latino? No te preocupes, es compatible, consulta la sección dedicada.
BONUS : si te gusta el concepto pero te gustaría instalarlo rápida y fácilmente (¡en menos de 3 minutos, de verdad!), visita el proyecto SearchinGhostEasy.
Antes de sumergirse en la instalación y configuración, pruébelo usted mismo con esta demostración en vivo .
En esta demostración, el contenido de búsqueda proviene de la API de demostración oficial de Ghost (es decir, https://demo.ghost.io). Las opciones están configuradas de forma predeterminada para que cada palabra ingresada se busque en el título de las publicaciones, las etiquetas, el extracto y el contenido principal.
Por ejemplo, busque la palabra "mermelada". No existe en ningún título, extracto o etiqueta de publicación, pero se usa una vez en el artículo "Down The Rabbit Hole", por eso lo obtendrás como resultado.
Primero, actualice el archivo default.hbs
de su tema para incluir un campo de entrada y un elemento de salida para mostrar los resultados de la búsqueda. Luego, agregue un enlace al script SearchinGhost e inicialícelo con su propio CONTENT_API_KEY
. Para obtener la clave API de contenido, consulte la documentación oficial de Ghost.
< input id =" search-bar " >
< ul id =" search-results " > </ ul >
< script src =" https://cdn.jsdelivr.net/npm/[email protected]/dist/searchinghost.min.js " > </ script >
< script >
var searchinGhost = new SearchinGhost ( {
key : 'CONTENT_API_KEY'
} ) ;
</ script >
¡Eso es todo, todo está hecho! Si necesita una configuración más detallada, lea las siguientes secciones.
Puede instalar SearchinGhost utilizando varios métodos, estas son las posibilidades:
Este es el método más sencillo y preferido para instalar SearchinGhost. Agregue uno de estos scripts a su tema default.hbs
. También recomendamos el uso de jsdelivr en lugar de unpkg por su confiabilidad y rendimiento.
< script src =" https://cdn.jsdelivr.net/npm/[email protected]/dist/searchinghost.min.js " > </ script >
<!-- OR -->
< script src =" https://unpkg.com/[email protected]/dist/searchinghost.min.js " > </ script >
Si desea servir SearchinGhost desde su propio servidor o incluirlo en su proceso de compilación, puede obtenerlo desde los recursos de la página de lanzamiento o descargar el archivo dist/searchinghost.min.js
.
Instale SearchinGhost como una dependencia del proyecto.
$ npm install searchinghost
# OR
$ yarn add searchinghost
Luego, cárguelo desde cualquier archivo Javascript.
import SearchinGhost from 'searchinghost' ;
// OR
var SearchinGhost = require ( 'searchinghost' ) ;
El único campo de configuración obligatorio es key
. Cualquier otro campo tiene un valor predeterminado y se vuelve opcional.
SearchinGhost ha sido diseñado para funcionar desde el primer momento, ¡esta configuración mínima es pero poderosa! Con cada pulsación de tecla, buscará el título, las etiquetas, el extracto y el contenido de las publicaciones. Este es el comportamiento predeterminado, ya que parece ser el más común.
// SearchinGhost minimal configuration
var searchinGhost = new SearchinGhost ( {
key : '<CONTENT_API_KEY>'
} ) ;
Sin embargo, podría valer la pena realizar un poco de configuración adicional para satisfacer sus necesidades. Digamos que solo desea buscar el title
y mostrar los campos title
y published_at
para cada publicación encontrada. Podrías usar esta configuración:
var searchinGhost = new SearchinGhost ( {
key : '<CONTENT_API_KEY>' ,
postsFields : [ 'title' , 'url' , 'published_at' ] ,
postsExtraFields : [ ] ,
postsFormats : [ ] ,
indexedFields : [ 'title' ] ,
template : function ( post ) {
return `<a href=" ${ post . url } "> ${ post . published_at } - ${ post . title } </a>`
}
} ) ;
SearchinGhost es fácilmente personalizable y extensible a través de su configuración; tómate tu tiempo para analizar cada opción de la siguiente sección.
{
key : '' ,
url : window . location . origin ,
version : 'v3' ,
loadOn : 'focus' ,
searchOn : 'keyup' ,
limit : 10 ,
inputId : [ 'search-bar' ] ,
outputId : [ 'search-results' ] ,
outputChildsType : 'li' ,
postsFields : [ 'title' , 'url' , 'excerpt' , 'custom_excerpt' , 'published_at' , 'feature_image' ] ,
postsExtraFields : [ 'tags' ] ,
postsFormats : [ 'plaintext' ] ,
indexedFields : [ 'title' , 'string_tags' , 'excerpt' , 'plaintext' ] ,
template : function ( post ) {
var o = `<a href=" ${ post . url } ">`
if ( post . feature_image ) o += `<img src=" ${ post . feature_image } ">`
o += '<section>'
if ( post . tags . length > 0 ) {
o += `<header>
<span class="head-tags"> ${ post . tags [ 0 ] . name } </span>
<span class="head-date"> ${ post . published_at } </span>
</header>`
} else {
o += `<header>
<span class="head-tags">UNKNOWN</span>
<span class="head-date"> ${ post . published_at } </span>
</header>`
}
o += `<h2> ${ post . title } </h2>`
o += `</section></a>`
return o ;
} ,
emptyTemplate : function ( ) { } ,
customProcessing : function ( post ) {
if ( post . tags ) post . string_tags = post . tags . map ( o => o . name ) . join ( ' ' ) . toLowerCase ( ) ;
return post ;
} ,
date : {
locale : document . documentElement . lang || "en-US" ,
options : { year : 'numeric' , month : 'short' , day : 'numeric' }
} ,
cacheMaxAge : 1800 ,
onFetchStart : function ( ) { } ,
onFetchEnd : function ( posts ) { } ,
onIndexBuildStart : function ( ) { } ,
onIndexBuildEnd : function ( index ) { } ,
onSearchStart : function ( ) { } ,
onSearchEnd : function ( posts ) { } ,
indexOptions : { } ,
searchOptions : { } ,
debug : false
} ) ;
La clave API de contenido público para obtener acceso a los datos del blog.
ejemplo:
'22444f78447824223cefc48062'
El nombre de dominio completo de la API de Ghost.
ejemplo:
'https://demo.ghost.io'
predeterminado:
window.location.origin
Establezca la versión de la API de Ghost. Trabaje tanto con
'v2'
como con'v3'
.predeterminado:
'v3'
Establezca la estrategia de carga de la biblioteca. Puede activarse cuando se ha cargado la página HTML, a pedido cuando el usuario hace clic en la barra de búsqueda o nunca.
Para activar la inicialización de la barra de búsqueda usted mismo, establezca este valor en
false
(booleano). De esta manera, puedes llamarsearchinGhost.loadData()
cuando el resto de tu código esté listo.valores esperados:
'page'
,'focus'
ofalse
predeterminado:
'focus'
Elija cuándo se debe ejecutar la consulta de búsqueda. Para buscar en cada pulsación de tecla de usuario y envío de formulario, utilice
'keyup'
. Para buscar solo cuando el usuario envía el formulario mediante un botón o ingresando la tecla "enter", use'submit'
. Si desea tener un control completo desde su propio código javascript, usefalse
(booleano) y ejecute la búsqueda usted mismo usandosearchinGhost.search("...")
.valores esperados:
'keyup'
,'submit'
ofalse
predeterminado:
'keyup'
Establezca el número máximo de publicaciones devueltas por una consulta de búsqueda. Cualquier valor entre
1
y50
será increíblemente rápido y un valor inferior a1000
no debería degradar demasiado el rendimiento. Pero recuerda, cuando el motor de búsqueda alcanza este límite deja de buscar y devuelve los resultados: cuanto más bajo, mejor.Aunque se desaconseja encarecidamente, establezca este valor en
0
para mostrar todos los resultados disponibles.predeterminado:
10
[Obsoleto] Antes de
v1.6.0
, este campo era unastring
, este comportamiento ha quedado obsoleto.Su sitio web puede tener una o varias barras de búsqueda, cada una de ellas debe tener un atributo
id
HTML único. Coloque cadaid
de la barra de búsqueda en esta matriz. No incluya '#' en el nombre.Si no necesita ningún campo de entrada, establezca el valor en
[]
(matriz vacía) y también establezcasearchOn
enfalse
(booleano). Luego, ejecute una búsqueda usandosearchinGhost.search("<your query>")
.predeterminado:
['search-bar']
[Obsoleto] Antes de
v1.6.0
, este campo era unastring
, este comportamiento ha quedado obsoleto.Su sitio web puede utilizar uno o más elementos HTML para mostrar los resultados de la búsqueda. Esta matriz hace referencia al atributo
id
de todos estos elementos de salida. Si alguno de estos elementos ya tiene contenido, los resultados de la búsqueda lo sobrescribirán.Si está utilizando un marco JS para mostrar los resultados de la búsqueda, establezca este valor en
[]
(matriz vacía). Obtendrá las publicaciones encontradas como el valor devuelto por la funciónsearchinGhost.search("<your query>")
.predeterminado:
['search-results']
[Obsoleto] Antes de
v1.6.0
, este campo era unastring
. esto ha quedado obsoleto.Cada resultado de la búsqueda se incluye dentro de un elemento secundario antes de agregarse al elemento principal
outputId
. El tipo predeterminado esli
, pero puede configurarlo en cualquier elemento HTML válido (consulte los documentos de MDN).Si no desea utilizar un elemento envolvente para agregar directamente los resultados de
template
yemptyTemplate
al elemento de salida, establezca el valor enfalse
(booleano).predeterminado:
'li'
Una serie de todos los campos de publicaciones deseadas. Todos estos campos estarán disponibles en la función
template
para mostrar información útil de las publicaciones.Consulte la documentación oficial de "campos".
Nota: si usa
'custom_excerpt'
, su contenido se colocará automáticamente en'excerpt'
para facilitar la creación de plantillas.predeterminado:
['title', 'url', 'excerpt', 'custom_excerpt', 'published_at', 'feature_image']
Esta matriz le permite utilizar campos adicionales como
tags
oauthors
. Personalmente no sé por qué no están con los otros "campos", pero la API de Ghost está diseñada de esta manera...Establezca su valor en
[]
(matriz vacía) para deshabilitarlo por completo.Consulte la documentación oficial "incluir".
predeterminado:
['tags']
Esto corresponde a la API Ghost de "formatos" que permite recuperar el contenido de las publicaciones con HTML o texto sin formato.
Establezca su valor en
[]
(matriz vacía) para deshabilitarlo por completo.Consulte la documentación oficial de "formatos".
predeterminado:
['plaintext']
Lista de campos indexados. El contenido de todos estos campos se podrá buscar.
Todos los valores de esta lista deben definirse en las publicaciones. De lo contrario, el resultado de la búsqueda no será preciso pero la aplicación no fallará. Verifique los valores
postsFields
,postsExtraFields
ypostsFormats
.NOTA : el campo extraño
'string_tags'
se agrega en la opcióncustomProcessing
. Si desea utilizar etiquetas, esta cosa fea es necesaria (por ahora) porque FlexSearch no puede manejar matrices correctamente. Si no lo desea o no le gusta, anule elcustomProcessing
para devolver soloposts
sin modificaciones adicionales. Si decide utilizar etiquetas, utilice también'string_tags'
aquí.predeterminado:
['title', 'string_tags', 'excerpt', 'plaintext']
Defina su propia plantilla de resultados. Esta plantilla se utilizará para cada publicación encontrada para generar el resultado y se agregará como elemento secundario al elemento de salida. No hay un motor de plantillas, solo una función nativa de JavaScript que utiliza un objeto
post
como argumento.Esta opción de plantilla es mucho más poderosa de lo que cabría esperar. También podemos considerarlo como una función de procesamiento personalizada llamada a los resultados de la búsqueda. Por ejemplo, si desea realizar algún filtrado, no devuelva nada (p. ej.,
return;
) o una cadena vacía (p. ej.,return "";
) para descartar un elemento.Tenga en cuenta el uso de comillas invertidas (por ejemplo, '`') en lugar de comillas simples o dobles. Esto es necesario para habilitar la muy útil interpolación de variables de JavaScript.
Las variables disponibles son las definidas en la opción
postsFields
.ejemplo:
template: function ( post ) { return `<a href=" ${ post . url } "># ${ post . tags } - ${ post . published_at } - ${ post . title } </a>` }
Defina su propia plantilla de resultados cuando no se encuentre ningún resultado.
ejemplo:
emptyTemplate: function ( ) { return '<p>Sorry, nothing found...</p>' }
¿Necesitas hacer alguna modificación adicional en los datos de las publicaciones obtenidas de Ghost? Utilice esta función para hacer lo que necesite. Esta función se llama en cada publicación y se ejecuta después de
onFetchEnd()
y antes deonIndexBuildStart()
.Si desea descartar una publicación, devuelva cualquier valor falso de JS (por ejemplo,
null
,undefined
,false
,""
, ...).Para depurar fácilmente sus entradas/salidas, use
onFetchEnd()
yonIndexBuildEnd()
para mostrar el resultado conconsole.log()
. Si eres un usuario más avanzado, la mejor opción sigue siendo utilizar el depurador. Además, ¡no olvide limpiar su caché local cuando realice la prueba!nota : de forma predeterminada, esta opción ya está completa con una función auxiliar para facilitar el uso del campo "etiquetas" en las publicaciones. Vea las opciones de
indexedFields
.ejemplo:
customProcessing: function ( post ) { post . extra_field = "hello" ; return post ; }
Defina el formato de fecha obtenido de las publicaciones.
Consulte la referencia de MDN para obtener más información.
ejemplo:
date: { locale : "fr-FR" , options : { weekday : 'long' , year : 'numeric' , month : 'long' , day : 'numeric' } }
Establezca la antigüedad máxima de la caché en segundos. Durante este período de tiempo, si se encuentra un índice ya existente en el almacenamiento local, se cargará sin ninguna solicitud HTTP adicional para confirmar su validez. Cuando se borra el caché, el valor se restablece.
Esto es especialmente útil para ahorrar las cargas de red y de banda ancha de su servidor. El valor predeterminado está establecido en media hora. Este valor proviene de la duración de la sesión de usuario predeterminada utilizada por Google Analytics.
predeterminado:
1800
Defina una función de devolución de llamada antes de recuperar los datos de la API de Ghost.
Esta función no acepta argumentos.
ejemplo:
onFetchStart: function ( ) { console . log ( "before data fetch" ) ; }
Defina una función de devolución de llamada cuando se complete la búsqueda. Incluso si las modificaciones realizadas en
posts
persisten, recomendamos el uso de la funcióncustomProcessing()
para hacerlo.La función toma un argumento: la matriz de todas las publicaciones devueltas por el propio Ghost.
ejemplo:
onFetchEnd: function ( posts ) { console . log ( "Total posts found on Ghost:" , posts . length ) ; }
Defina una función de devolución de llamada antes de comenzar a crear el índice de búsqueda.
La función no acepta argumentos.
ejemplo:
onIndexBuildStart: function ( ) { console . log ( "before building the index" ) ; }
Defina una función de devolución de llamada cuando se complete la creación del índice de búsqueda.
La función toma un argumento: el objeto de índice FlexSearch de compilación.
ejemplo:
onIndexBuildEnd: function ( index ) { console . log ( "index built:" , index ) ; }
Defina una función de devolución de llamada antes de comenzar a ejecutar la consulta de búsqueda. Por ejemplo, podría usarse para ocultar el elemento HTML de resultados mientras se espera que finalice
onSearchEnd
o agregar efectos de transición sofisticados. Pero en la mayoría de los casos, esto no es necesario porque la función de búsqueda es lo suficientemente rápida como para ser agradable a la vista.La función no acepta argumentos.
ejemplo:
onSearchStart: function ( ) { console . log ( "before executing the search query" ) ; }
Defina una función de devolución de llamada cuando los resultados de la búsqueda estén listos.
La función toma 1 argumento: la matriz de publicaciones coincidentes.
ejemplo:
onSearchEnd: function ( posts ) { console . log ( "search complete, posts found:" , posts ) ; }
Agregue una configuración de índice de búsqueda adicional o anule las predeterminadas. Estas opciones se fusionarán con la ya proporcionada:
{ doc : { id : "id" , field : this . config . indexedFields } , encode : "simple" , tokenize : "forward" , threshold : 0 , resolution : 4 , depth : 0 }Utilice también este parámetro para habilitar la compatibilidad con idiomas no latinos; consulte esta sección.
por defecto:
{}
Diseñado para usuarios avanzados, le permite ajustar las consultas de búsqueda. Consulte esta documentación de FlexSearch.
Usamos esta construcción de consulta específica:
index.search("your query", searchOptions)
para que todo lo que se agregue asearchOptions
se pase a FlexSearch de esta manera.Este parámetro puede resultar muy útil al filtrar publicaciones según una etiqueta. Como ejemplo:
searchOptions: { where : { string_tags : "getting started" } }También tenga en cuenta que la opción
limit
Searchinghost se fusiona automáticamente consearchOptions
. En nuestro caso finalmente quedaría como:searchOptions: { where : { string_tags : "getting started" } , limit : 10 }por defecto:
{}
Cuando algo no funciona como se esperaba, configúrelo en
true
para mostrar los registros de la aplicación.predeterminado:
false
Si su blog utiliza un idioma con alfabeto latino (por ejemplo, inglés, francés, español) o uno de Europa del Norte y del Este (por ejemplo, alemán, sueco, húngaro, esloveno, estonio), la configuración predeterminada funcionará bien. En los otros casos, busque el valor indexOptions
apropiado y agréguelo a su configuración principal de SearchinGhost.
Para crear sus propias configuraciones específicas, consulte el archivo README de FlexSearch y estos tres temas.
Si nada funciona para usted o si el comportamiento resultante no es correcto, no dude en crear un problema.
indexOptions: {
encode : false ,
rtl : true ,
split : / s+ /
}
indexOptions: {
encode : false ,
tokenize : function ( str ) {
return str . replace ( / [x00-x7F] / g , "" ) . split ( "" ) ;
}
}
Esta opción puede ser utilizada por cualquier idioma de palabras separadas por espacios que utilice caracteres complejos.
indexOptions: {
encode : false ,
split : / s+ /
}
Si necesita utilizar varios tipos de idiomas (por ejemplo, cirílico/inglés o indio/español), utilice la configuración dedicada a continuación. Lo sé, puede parecer aterrador a primera vista, pero simplemente cópialo y pégalo y confía en mí.
indexOptions: {
split : / s+ / ,
encode : function ( str ) {
var regexp_replacements = {
"a" : / [àáâãäå] / g ,
"e" : / [èéêë] / g ,
"i" : / [ìíîï] / g ,
"o" : / [òóôõöő] / g ,
"u" : / [ùúûüű] / g ,
"y" : / [ýŷÿ] / g ,
"n" : / ñ / g ,
"c" : / [ç] / g ,
"s" : / ß / g ,
" " : / [-/] / g ,
"" : / ['!"#$%&\()*+,-./:;<=>?@[]^_`{|}~] / g ,
" " : / s+ / g ,
}
str = str . toLowerCase ( ) ;
for ( var key of Object . keys ( regexp_replacements ) ) {
str = str . replace ( regexp_replacements [ key ] , key ) ;
}
return str === " " ? "" : str ;
}
}
Al principio, también probamos estas otras soluciones: Lunr.js, minisearch y fuse.js. Al final, FlexSearch ofreció los mejores resultados generales con resultados rápidos y precisos , un tamaño de paquete lo suficientemente pequeño y también fue fácil de configurar. ¡Tiene todo para ser elegido!
No te preocupes, es normal. SearchinGhost utiliza un sistema de caché para almacenar los datos de su blog en el navegador y limitar la interacción de la red. De forma predeterminada, los datos almacenados en caché hace menos de 30 minutos todavía se consideran válidos. Pasado ese tiempo, el nuevo artículo estará disponible para ti.
Tenga en cuenta que es posible que otros usuarios no necesiten esperar 30 minutos dependiendo de la última vez que realizaron una investigación. Si lo estuvo hace 1 hora, su caché se borrará y renovará para que aparezca el artículo.
Si desea que sus usuarios estén siempre perfectamente actualizados, establezca cacheMaxAge
en 0
. Al hacerlo, también debe configurar loadOn
en 'focus'
para limitar la cantidad de solicitudes HTTP.
De forma predeterminada, cuando usa la variable URL feature_image
para mostrar imágenes en sus resultados de búsqueda, siempre obtendrá la original/de tamaño completo y generalmente son demasiado grandes (en tamaño y peso) para nuestras necesidades, una miniatura sería mejor. adaptar.
Desde Ghost V3, se incorpora un motor de procesamiento de medios para crear imágenes responsivas. De forma predeterminada, Ghost recrea 6 imágenes diferentes de la dada. Los tamaños disponibles son: w30
, w100
, w300
, w600
, w1000
, w2000
.
En nuestro caso, la forma más sencilla de cargar imágenes más rápido es simplemente utilizar imágenes más pequeñas. Básicamente, queremos que esta URL https://www.example.fr/content/images/2020/05/picture.jpg
(la predeterminada obtenida de la API de Ghost) se convierta en https://www.example.fr/content/images/size/w600/2020/05/picture.jpg
(el de 600px de ancho).
Para hacerlo, actualice la configuración agregando un campo "customProcessing"
con el siguiente ejemplo de código. Por supuesto, puedes utilizar cualquiera de los tamaños disponibles mencionados anteriormente en lugar del w600
.
customProcessing: function ( post ) {
if ( post . tags ) post . string_tags = post . tags . map ( o => o . name ) . join ( ' ' ) . toLowerCase ( ) ;
if ( post . feature_image ) post . feature_image = post . feature_image . replace ( '/images/' , '/images/size/w600/' ) ; // reduce image size to w600
return post ;
}
Esta modificación no es inmediata; necesita una actualización de la caché para ver realmente la diferencia.
Cree un elemento HTML con el ID "search-counter"
y aproveche la función onSearchEnd()
para completarlo con el resultado. Aquí hay un ejemplo:
< p id =" search-counter " > </ p >
onSearchEnd: function ( posts ) {
var counterEl = document . getElementById ( 'search-counter' ) ;
counterEl . textContent = ` ${ posts . length } posts found` ;
}
Sí, utilizando los métodos internos de SearchinGhost, pero es posible. Puede parecer magia negra, pero agregue el siguiente código a su configuración actual. Aquí, searchinGhost
se refiere a su propia instancia creada con new SearchinGhost(...)
.
emptyTemplate: function ( ) {
var allPostsArray = Object . values ( searchinGhost . index . l ) ;
var latestPosts = allPostsArray . slice ( 0 , 6 ) ;
searchinGhost . display ( latestPosts ) ;
}
Si está utilizando un marco como React, Vue o Angular, probablemente no desee permitir que SearchinGhost manipule el DOM por sí solo. Debido a que definitivamente necesitas mantener cualquier actualización de contenido dentro de tu marco, esta es la configuración que debes usar:
var searchinGhost = new SearchinGhost ( {
key : '<CONTENT_API_KEY>' ,
inputId : false ,
outputId : false ,
[ ... ]
} ) ;
Ahora, para ejecutar una consulta de búsqueda, llame a este método SearchinGhost:
var postsFound = searchinGhost . search ( "my query" ) ;
// Where 'postsFound' content looks like:
[
{
"title" : "A Full and Comprehensive Style Test" ,
"published_at" : "Sep 1, 2012" ,
[ ... ]
} ,
{
"title" : "Publishing options" ,
"published_at" : "Aug 20, 2018" ,
[ ... ]
}
]
De esta manera, nada se renderizará a tus espaldas y todo permanecerá bajo control en ShadowDom.
debug: true
onFetchStart()
, onSearchStart()
, ... De ahora en adelante, cualquier modificación se rastrea en este archivo CHANGELOG.md dedicado.
¡Cualquier contribución es más que bienvenida! Si encontró un error o desea mejorar el código, no dude en crear un problema o un PR.
Todas las actualizaciones del código deben realizarse en el directorio src
.
Para construir el proyecto usted mismo, ejecute:
$ npm install
$ npm run build
Al desarrollar, utilice el comando watch en su lugar, se reconstruirá más rápido con cada modificación del archivo e incluirá un enlace al mapa fuente que facilitará la depuración.
$ npm run watch
Nota: mientras creo este proyecto, estoy usando Node v12.16.2 con NPM v6.14.4, pero también debería funcionar con versiones anteriores/nuevas.
SearchinGhost no está solo en el campo de los complementos de búsqueda de Ghost. Aquí hay una breve lista de otros proyectos relacionados. Definitivamente deberías probarlos para ver si se ajustan mejor a tus necesidades:
GhostHunter (v0.6.0 - 101 kB, 26 kB gzip)
Ventajas:
- El más famoso, muchos artículos y tutoriales al respecto.
- Un potente sistema de caché basado en localStorage
- Indexación de texto completo (no solo el título de las publicaciones)
Contras:
- Se basa en jQuery
- Solo funciona con la API Ghost v2 (por ahora)
- El código fuente se volvió confuso con el tiempo.
búsqueda fantasma (v1.1.0 - 12 kB, 4,2 kB gzip)
Ventajas:
- Base de código bien escrita y fácil de leer.
- Aprovechar las capacidades 'difusas'
Contras:
- El navegador se retrasa al buscar palabras largas
- Podría enviar demasiadas solicitudes de API
- No utiliza un sistema de puntuación para mostrar los mejores resultados primero.
Buscador de fantasmas (v3.1.2 - 459 kB, 116 kB gzip)
Ventajas:
- Biblioteca Javascript pura
Contras:
- El enorme tamaño del paquete final
- ¡Envíe una solicitud HTTP por cada tecla presionada!
- No utiliza motor de búsqueda, solo busca subcadenas en los títulos de las publicaciones.
- No indexa correctamente los caracteres acentuados (por ejemplo, 'é' debe encontrarse con 'e')