Um plugin de pesquisa de texto completo em javascript puro, leve e no navegador para Ghost (blog)
SearchinGhost é um mecanismo de pesquisa leve e extensível dedicado à plataforma de blogs Ghost. Basicamente, ele usa a API Ghost Content para carregar o conteúdo do seu blog e a poderosa biblioteca FlexSearch para indexar e executar consultas de pesquisa.
Tudo acontece no navegador do cliente, isso nos ajuda a fornecer resultados de pesquisa extremamente rápidos e exibi-los em tempo real para seus usuários (também conhecido como "pesquise enquanto você digita"). Também tomamos cuidado em minimizar as cargas de rede, contando com o navegador localStorage
enviando solicitações apenas quando necessário.
Seu blog está em cirílico, chinês, coreano, grego, indiano ou qualquer outro idioma não latino? Não se preocupe, é compatível, consulte a seção dedicada.
BÔNUS : se você gosta do conceito, mas gostaria de instalá-lo de forma rápida e fácil (em menos de 3 minutos, na verdade!), visite o projeto SearchinGhostEasy.
Antes de mergulhar na instalação e configuração, experimente você mesmo com esta demonstração ao vivo .
Nesta demonstração, o conteúdo pesquisável vem da API de demonstração oficial do Ghost (ou seja, https://demo.ghost.io). As opções são definidas como padrão para que cada palavra de entrada seja pesquisada no título da postagem, tags, trecho e conteúdo principal.
Por exemplo, pesquise a palavra “marmelada”. Ele não existe em nenhum título de postagem, trecho ou tag, mas é usado uma vez no artigo "Down The Rabbit Hole", por isso você o obterá como resultado.
Primeiro, atualize o arquivo default.hbs
do seu tema para incluir um campo de entrada e um elemento de saída para exibir os resultados da pesquisa. Em seguida, adicione um link para o script SearchinGhost e inicialize-o com seu próprio CONTENT_API_KEY
. Para obter a chave da API de conteúdo, consulte a documentação oficial do 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 >
É isso, está tudo feito! Se você precisar de uma configuração mais refinada, leia as próximas seções.
Você pode instalar o SearchinGhost usando vários métodos, aqui estão as possibilidades:
Este é o método mais fácil e preferido para instalar o SearchinGhost. Adicione um desses scripts ao seu tema default.hbs
. Também recomendamos o uso de jsdelivr em vez de unpkg por sua confiabilidade e desempenho.
< 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 >
Se você deseja servir o SearchinGhost a partir de seu próprio servidor ou incluí-lo em seu processo de construção, você pode obtê-lo nos ativos da página de lançamento ou baixar o arquivo dist/searchinghost.min.js
.
Instale o SearchinGhost como uma dependência do projeto.
$ npm install searchinghost
# OR
$ yarn add searchinghost
Em seguida, carregue-o de qualquer arquivo Javascript.
import SearchinGhost from 'searchinghost' ;
// OR
var SearchinGhost = require ( 'searchinghost' ) ;
O único campo de configuração obrigatório é key
. Qualquer outro campo possui um valor padrão e tornou-se opcional.
SearchinGhost foi projetado para funcionar imediatamente, esta configuração mínima é ainda poderosa! A cada toque de tecla, ele pesquisará o título, as tags, o trecho e o conteúdo das postagens. Este é o comportamento padrão, pois parece ser o mais comum.
// SearchinGhost minimal configuration
var searchinGhost = new SearchinGhost ( {
key : '<CONTENT_API_KEY>'
} ) ;
No entanto, um pouco de configuração extra pode valer a pena para atender às suas necessidades. Digamos que você queira apenas pesquisar o title
e exibir os campos title
e published_at
para cada postagem encontrada. Você poderia usar esta configuração:
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 é facilmente personalizável e extensível por meio de sua configuração. Reserve um tempo para examinar cada opção na próxima seção.
{
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
} ) ;
A chave da API de conteúdo público para obter acesso aos dados do blog.
exemplo:
'22444f78447824223cefc48062'
O nome de domínio completo da API Ghost.
exemplo:
'https://demo.ghost.io'
padrão:
window.location.origin
Defina a versão da API Ghost. Trabalhe com
'v2'
e'v3'
.padrão:
'v3'
Defina a estratégia de carregamento da biblioteca. Pode ser acionado quando a página HTML é carregada, sob demanda quando o usuário clica na barra de pesquisa ou nunca.
Para acionar você mesmo a inicialização da barra de pesquisa, defina esse valor como
false
(booleano). Dessa forma, você pode chamarsearchinGhost.loadData()
quando o resto do seu código estiver pronto.valores esperados:
'page'
,'focus'
oufalse
padrão:
'focus'
Escolha quando a consulta de pesquisa deve ser executada. Para pesquisar a cada pressionamento de tecla do usuário e envio de formulário, use
'keyup'
. Para pesquisar apenas quando o usuário enviar o formulário através de um botão ou digitando a tecla 'enter', use'submit'
. Se você deseja ter um controle completo dele a partir de seu próprio código javascript, usefalse
(booleano) e execute a pesquisa sozinho usandosearchinGhost.search("...")
.valores esperados:
'keyup'
,'submit'
oufalse
padrão:
'keyup'
Defina o número máximo de postagens retornadas por uma consulta de pesquisa. Qualquer valor entre
1
e50
será extremamente rápido e valores inferiores a1000
não devem degradar muito o desempenho. Mas lembre-se, quando o mecanismo de busca atinge esse limite ele para de pesquisar e retorna os resultados: quanto menor, melhor.Mesmo que seja fortemente desencorajado, defina este valor como
0
para exibir todos os resultados disponíveis.padrão:
10
[Obsoleto] Antes da
v1.6.0
, este campo era umastring
, esse comportamento foi descontinuado.Seu site pode ter uma ou várias barras de pesquisa, cada uma delas deve ter um atributo HTML
id
exclusivo. Coloque cadaid
da barra de pesquisa nesta matriz. Não inclua '#' no nome.Se você não precisar de nenhum campo de entrada, defina o valor como
[]
(matriz vazia) e também definasearchOn
comofalse
(booleano). Em seguida, execute uma pesquisa usandosearchinGhost.search("<your query>")
.padrão:
['search-bar']
[Obsoleto] Antes da
v1.6.0
, este campo era umastring
, esse comportamento foi descontinuado.Seu site pode usar um ou mais elementos HTML para exibir os resultados da pesquisa. Esta matriz faz referência a todos os atributos
id
desses elementos de saída. Se algum desses elementos já tiver conteúdo, ele será substituído pelos resultados da pesquisa.Se você estiver usando uma estrutura JS para exibir os resultados da pesquisa, defina esse valor como
[]
(matriz vazia). Você obterá as postagens encontradas como o valor retornado pela funçãosearchinGhost.search("<your query>")
.padrão:
['search-results']
[Obsoleto] Antes da
v1.6.0
, esse campo era umastring
. isso foi descontinuado.Cada resultado da pesquisa é agrupado em um elemento filho antes de ser adicionado ao elemento pai
outputId
. O tipo padrão éli
, mas você pode configurá-lo para qualquer elemento HTML válido (consulte a documentação do MDN).Se você não quiser usar um elemento de encapsulamento para anexar diretamente os resultados de
template
eemptyTemplate
ao elemento de saída, defina o valor comofalse
(booleano).padrão:
'li'
Uma matriz de todos os campos de postagens desejados. Todos esses campos ficarão disponíveis na função
template
para exibir informações úteis sobre postagens.Consulte a documentação oficial dos "campos".
Nota: se você usar
'custom_excerpt'
, seu conteúdo será automaticamente colocado em'excerpt'
para facilitar a modelagem.padrão:
['title', 'url', 'excerpt', 'custom_excerpt', 'published_at', 'feature_image']
Essa matriz permite usar campos extras como
tags
ouauthors
. Pessoalmente, não sei por que eles não estão com os outros "campos", mas a API do Ghost foi projetada desta forma...Defina seu valor como
[]
(matriz vazia) para desativá-lo completamente.Consulte a documentação oficial "incluir".
padrão:
['tags']
Isso corresponde à API Ghost de "formatos" que permite buscar o conteúdo das postagens com HTML ou texto simples.
Defina seu valor como
[]
(matriz vazia) para desativá-lo completamente.Consulte a documentação oficial dos "formatos".
padrão:
['plaintext']
Lista de campos indexados. O conteúdo de todos esses campos será pesquisável.
Todos os valores desta lista devem ser definidos nas postagens. Caso contrário, o resultado da pesquisa não será preciso, mas o aplicativo não travará! Verifique novamente os valores
postsFields
,postsExtraFields
epostsFormats
.NOTA : o campo estranho
'string_tags'
é adicionado na opçãocustomProcessing
. Se você quiser usar tags, essa coisa feia é necessária (por enquanto) porque o FlexSearch não consegue lidar com arrays adequadamente. Se você não quiser/gostar, substituacustomProcessing
para retornar apenasposts
sem modificações adicionais. Se você decidir usar tags, use também'string_tags'
aqui.padrão:
['title', 'string_tags', 'excerpt', 'plaintext']
Defina seu próprio modelo de resultado. Este modelo será usado para cada postagem encontrada para gerar o resultado e anexado como elemento filho ao elemento de saída. Não há mecanismo de modelagem, apenas uma função javascript nativa usando um objeto
post
como argumento.Esta opção de modelo é muito mais poderosa do que você imagina. Também podemos pensar nisso como uma função de processamento personalizada chamada nos resultados da pesquisa. Por exemplo, se você quiser fazer alguma filtragem, não retorne nada (por exemplo,
return;
) ou uma string vazia (por exemplo,return "";
) para descartar um item.Observe o uso de crases (por exemplo, '`') em vez de aspas simples/duplas. Isso é necessário para ativar a interpolação de variáveis javascript muito útil.
As variáveis disponíveis são aquelas definidas na opção
postsFields
.exemplo:
template: function ( post ) { return `<a href=" ${ post . url } "># ${ post . tags } - ${ post . published_at } - ${ post . title } </a>` }
Defina seu próprio modelo de resultado quando nenhum resultado for encontrado.
exemplo:
emptyTemplate: function ( ) { return '<p>Sorry, nothing found...</p>' }
Você precisa fazer alguma modificação extra nos dados de postagens obtidos do Ghost? Use esta função para fazer o que precisar. Esta função é chamada em cada postagem, executada após
onFetchEnd()
e antes deonIndexBuildStart()
.Se você quiser descartar uma postagem, retorne qualquer valor JS falso (por exemplo,
null
,undefined
,false
,""
, ...).Para depurar facilmente suas entradas/saídas, use
onFetchEnd()
eonIndexBuildEnd()
para exibir o resultado comconsole.log()
. Se você é um usuário mais avançado, a melhor opção ainda é usar o depurador. Além disso, não se esqueça de limpar o cache local durante o teste!nota : por padrão, esta opção já vem preenchida com uma função auxiliar para facilitar o uso do campo "tags" nas postagens. Veja as opções
indexedFields
.exemplo:
customProcessing: function ( post ) { post . extra_field = "hello" ; return post ; }
Defina o formato de data obtido nas postagens.
Consulte a referência do MDN para obter mais informações.
exemplo:
date: { locale : "fr-FR" , options : { weekday : 'long' , year : 'numeric' , month : 'long' , day : 'numeric' } }
Defina a idade máxima do cache em segundos. Durante esse período, se um índice já existente for encontrado no armazenamento local, ele será carregado sem qualquer solicitação HTTP adicional para confirmar sua validade. Quando o cache é limpo, o valor é redefinido.
Isso é especialmente útil para economizar as cargas de banda larga e de rede do seu servidor. O valor padrão é definido como meia hora. Este valor vem da duração padrão da sessão do usuário usada pelo Google Analytics.
padrão:
1800
Defina uma função de retorno de chamada antes de buscarmos os dados da API Ghost.
Esta função não aceita argumentos.
exemplo:
onFetchStart: function ( ) { console . log ( "before data fetch" ) ; }
Defina uma função de retorno de chamada quando a busca for concluída. Mesmo que as modificações feitas nas
posts
persistam, recomendamos o uso da funçãocustomProcessing()
para fazer isso.A função recebe um argumento: o array de todas as postagens retornadas pelo próprio Ghost.
exemplo:
onFetchEnd: function ( posts ) { console . log ( "Total posts found on Ghost:" , posts . length ) ; }
Defina uma função de retorno de chamada antes de começarmos a construir o índice de pesquisa.
A função não aceita argumentos.
exemplo:
onIndexBuildStart: function ( ) { console . log ( "before building the index" ) ; }
Defina uma função de retorno de chamada quando a construção do índice de pesquisa for concluída.
A função recebe um argumento: o objeto de índice FlexSearch de construção.
exemplo:
onIndexBuildEnd: function ( index ) { console . log ( "index built:" , index ) ; }
Defina uma função de retorno de chamada antes de iniciar a execução da consulta de pesquisa. Por exemplo, ele pode ser usado para ocultar o elemento HTML de resultados enquanto aguarda a conclusão
onSearchEnd
ou adicionar quaisquer efeitos de transição sofisticados. Mas na maioria dos casos, isso não é necessário porque a função de pesquisa é rápida o suficiente para ser agradável à vista.A função não aceita argumentos.
exemplo:
onSearchStart: function ( ) { console . log ( "before executing the search query" ) ; }
Defina uma função de retorno de chamada quando os resultados da pesquisa estiverem prontos.
A função leva 1 argumento: a matriz de postagens correspondentes.
exemplo:
onSearchEnd: function ( posts ) { console . log ( "search complete, posts found:" , posts ) ; }
Adicione configurações extras de índice de pesquisa ou substitua as configurações padrão. Estas opções serão mescladas com a já fornecida:
{ doc : { id : "id" , field : this . config . indexedFields } , encode : "simple" , tokenize : "forward" , threshold : 0 , resolution : 4 , depth : 0 }Use também este parâmetro para ativar o suporte a idiomas não latinos, consulte esta seção.
padrão:
{}
Feito para usuários avançados, permite ajustar as consultas de pesquisa. Consulte esta documentação do FlexSearch.
Usamos esta construção de consulta específica:
index.search("your query", searchOptions)
então qualquer coisa adicionada asearchOptions
será passada para FlexSearch desta forma.Este parâmetro pode ser muito útil ao filtrar postagens com base em uma tag. Por exemplo:
searchOptions: { where : { string_tags : "getting started" } }Observe também que a opção
limit
Searchinghost é automaticamente mesclada emsearchOptions
. No nosso caso, finalmente se tornaria:searchOptions: { where : { string_tags : "getting started" } , limit : 10 }padrão:
{}
Quando algo não estiver funcionando conforme o esperado, defina como
true
para exibir os logs do aplicativo.padrão:
false
Se o seu blog usa um alfabeto latino (por exemplo, inglês, francês, espanhol) ou um idioma do Norte/Leste Europeu (por exemplo, alemão, sueco, húngaro, esloveno, estoniano), a configuração padrão funcionará perfeitamente. Nos outros casos, encontre o valor indexOptions
apropriado e adicione-o à configuração principal do SearchinGhost.
Para criar suas próprias configurações específicas, consulte o README do FlexSearch e estes três problemas.
Se nada funcionar para você ou se o comportamento resultante não estiver correto, sinta-se à vontade para criar um problema.
indexOptions: {
encode : false ,
rtl : true ,
split : / s+ /
}
indexOptions: {
encode : false ,
tokenize : function ( str ) {
return str . replace ( / [x00-x7F] / g , "" ) . split ( "" ) ;
}
}
Esta opção pode ser usada por qualquer idioma de palavra separada por espaço que utilize caracteres complexos.
indexOptions: {
encode : false ,
split : / s+ /
}
Se você precisar usar vários tipos de idiomas (por exemplo, cirílico/inglês ou indiano/espanhol), use a configuração dedicada abaixo. Eu sei, pode parecer assustador à primeira vista, mas basta copiar/colar e confiar em mim.
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 ;
}
}
A princípio, também tentamos estas outras soluções: Lunr.js, minisearch e fuse.js. No final, o FlexSearch ofereceu os melhores resultados gerais com resultados rápidos e precisos , um tamanho de pacote pequeno o suficiente e também foi fácil de configurar. Tem tudo para ser escolhido!
Não se preocupe, é normal. SearchinGhost usa um sistema de cache para armazenar os dados do seu blog no navegador e limitar a interação da rede. Por padrão, os dados armazenados em cache armazenados há menos de 30 minutos ainda são considerados válidos. Após esse período, o novo artigo estará disponível para você.
Lembre-se de que outros usuários podem não precisar esperar 30 minutos, dependendo da última vez que fizeram uma pesquisa. Se você estava há 1h, o cache deles será limpo e renovado para que o artigo apareça.
Se você deseja que seus usuários estejam sempre perfeitamente atualizados, defina cacheMaxAge
como 0
. Ao fazer isso, você também deve definir loadOn
como 'focus'
para limitar o número de solicitações HTTP.
Por padrão, quando você usa a variável de URL feature_image
para exibir imagens em seus resultados de pesquisa, você sempre obterá a imagem original/em tamanho real e elas geralmente são muito grandes (em tamanho e peso) para nossas necessidades, uma miniatura seria melhor ajustar.
Desde o Ghost V3, um mecanismo de processamento de mídia é incorporado para criar imagens responsivas. Por padrão, o Ghost recria 6 imagens diferentes de uma determinada. Os tamanhos disponíveis são: w30
, w100
, w300
, w600
, w1000
, w2000
.
No nosso caso, a maneira mais fácil de carregar imagens com mais rapidez é simplesmente usar imagens menores. Basicamente, queremos que este URL https://www.example.fr/content/images/2020/05/picture.jpg
(padrão obtido da API Ghost) se torne https://www.example.fr/content/images/size/w600/2020/05/picture.jpg
(o de largura de 600px).
Para fazer isso, atualize a configuração adicionando um campo "customProcessing"
com o exemplo de código a seguir. Claro, você pode usar qualquer tamanho disponível mencionado acima em vez de 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 modificação não é imediata, você precisa de uma atualização de cache para realmente ver a diferença.
Crie um elemento HTML com o ID "search-counter"
e aproveite a função onSearchEnd()
para preenchê-lo com o resultado. Aqui está um exemplo:
< p id =" search-counter " > </ p >
onSearchEnd: function ( posts ) {
var counterEl = document . getElementById ( 'search-counter' ) ;
counterEl . textContent = ` ${ posts . length } posts found` ;
}
Sim, usando métodos internos do SearchinGhost, mas é possível. Pode parecer magia negra, mas adicione o código abaixo à sua configuração atual. Aqui, searchinGhost
refere-se à sua própria instância criada com new SearchinGhost(...)
.
emptyTemplate: function ( ) {
var allPostsArray = Object . values ( searchinGhost . index . l ) ;
var latestPosts = allPostsArray . slice ( 0 , 6 ) ;
searchinGhost . display ( latestPosts ) ;
}
Se estiver usando uma estrutura como React, Vue ou Angular, você provavelmente não deseja deixar o SearchinGhost manipular o DOM sozinho. Como você definitivamente precisa manter qualquer atualização de conteúdo dentro da sua estrutura, aqui está a configuração que você deve usar:
var searchinGhost = new SearchinGhost ( {
key : '<CONTENT_API_KEY>' ,
inputId : false ,
outputId : false ,
[ ... ]
} ) ;
Agora, para executar uma consulta de pesquisa, chame 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" ,
[ ... ]
}
]
Dessa forma, nada será renderizado pelas suas costas e tudo ficará sob controle no shadowDom.
debug: true
onFetchStart()
, onSearchStart()
, ... De agora em diante, qualquer modificação será rastreada neste arquivo CHANGELOG.md dedicado.
Qualquer contribuição é mais que bem-vinda! Se você encontrou um bug ou gostaria de melhorar o código, sinta-se à vontade para criar um problema ou um PR.
Todas as atualizações de código devem ser feitas no diretório src
.
Para construir o projeto sozinho, execute:
$ npm install
$ npm run build
Ao desenvolver, use o comando watch, ele será reconstruído mais rapidamente a cada modificação do arquivo e incluirá um link para o mapa de origem que facilita a depuração.
$ npm run watch
Nota: ao criar este projeto estou usando o Node v12.16.2 com NPM v6.14.4, mas também deve funcionar com versões mais antigas/mais recentes
SearchinGhost não está sozinho no campo dos plug-ins de pesquisa do Ghost. Aqui está uma pequena lista de outros projetos relacionados. Definitivamente, você deve experimentá-los para ver se eles atendem melhor às suas necessidades:
GhostHunter (v0.6.0 - 101 kB, 26 kB gzip)
Prós:
- O mais famoso, muitos artigos e tutoriais sobre o assunto
- Um poderoso sistema de cache baseado em localStorage
- Indexação de texto completo (não apenas o título das postagens)
Contras:
- Depende de jQuery
- Funciona apenas com a API Ghost v2 (por enquanto)
- O código-fonte ficou confuso com o tempo
pesquisa fantasma (v1.1.0 - 12 kB, 4,2 kB gzip)
Prós:
- Base de código bem escrita e fácil de ler
- Aproveite recursos 'fuzzy'
Contras:
- O navegador fica lento ao pesquisar palavras longas
- Pode enviar muitas solicitações de API
- Não usa um sistema de pontuação para exibir os melhores resultados primeiro
Localizador de fantasmas (v3.1.2 - 459 kB, 116 kB gzip)
Prós:
- Biblioteca Javascript pura
Contras:
- O enorme tamanho final do pacote
- Envie uma solicitação HTTP para cada tecla pressionada!
- Não usa mecanismo de busca, apenas procura substrings nos títulos das postagens
- Não indexa corretamente caracteres acentuados (por exemplo, 'é' deve ser encontrado com 'e')