Pesquisa baseada em LunrJS para Middleman.
Adicione esta linha ao Gemfile da sua aplicação:
gem 'middleman-search'
E então execute:
$ bundle
Ou instale você mesmo como:
$ gem install middleman-search
Você precisa ativar o módulo no seu config.rb
, informando à extensão como indexar seus recursos:
activate :search do | search |
search . resources = [ 'blog/' , 'index.html' , 'contactus/index.html' ]
search . index_path = 'search/lunr-index.json' # defaults to `search.json`
search . lunr_dirs = [ 'source/vendor/lunr-custom/' ] # optional alternate paths where to look for lunr js files
search . language = 'es' # defaults to 'en'
search . fields = {
title : { boost : 100 , store : true , required : true } ,
content : { boost : 50 } ,
url : { index : false , store : true } ,
author : { boost : 30 }
}
end
Onde resources
é uma lista do início da URL dos recursos a serem indexados (testado com String#start_with?
), index_path
é o caminho relativo do arquivo de índice gerado em seu site e fields
é um hash com uma entrada para cada campo a ser indexado, com um hash de opções associado:
boost
Especifica o aumento de relevância lunr ao pesquisar este campostore
Se este campo deve ser armazenado no mapa do documento (veja abaixo), o padrão é falsoindex
Se este campo deve ser indexado, o padrão é verdadeirorequired
O recurso não será indexado se um campo marcado como obrigatório tiver um valor vazio ou nulo Observe que um id
de campo especial é incluído automaticamente, com um identificador gerado automaticamente para ser usado como ref
do documento.
Todos os valores dos campos são recuperados dos data
do recurso (ou seja, seu frontmatter) ou das options
no resource.metadata
(ou seja, quaisquer opções especificadas em uma página proxy
), exceto:
url
que é o URL real do recursocontent
o texto extraído do recurso renderizado, sem incluir seu layout Você pode então consultar o índice de Javascript por meio do objeto lunrIndex
(consulte Arquivo de índice para obter mais informações):
var max_search_entries = 50 ;
var result = [ ] ; //initialize empty array
lunrIndex . search ( request . term ) . forEach ( function ( item , index ) {
if ( index < max_search_entries ) {
result . push ( lunrData . docs [ item . ref ] ) ;
}
} ) ;
(Obrigado @Jeepler por adaptar o código lodash v3 que costumávamos usar em Manas)
Esta joia inclui recursos para idiomas alternativos fornecidos por MihaiValentin/lunr-idiomas. Consulte esse repositório para obter uma lista dos idiomas disponíveis.
Se você quiser trabalhar com uma linguagem que não está incluída, configure um arquivo lunr.yourlang.js
em uma pasta do seu projeto e adicione essa pasta a lunr_dirs
para que a gem saiba onde procurá-la.
Você pode personalizar totalmente o conteúdo a ser indexado e armazenado por recurso definindo um retorno de chamada before_index
:
activate :search do | search |
search . before_index = Proc . new do | to_index , to_store , resource |
if author = resource . data . author
to_index [ :author ] = data . authors [ author ] . name
end
end
end
Esta opção aceita um callback que será executado para cada recurso, e será executado com o documento a ser indexado e o mapa a ser armazenado, nos objetos index
e docs
da saída respectivamente (veja abaixo), bem como no recurso sendo processado. Você pode usar esse retorno de chamada para modificar qualquer um deles ou throw(:skip)
para ignorar o recurso em questão.
Em alguns casos, você pode querer adicionar uma nova função ao pipeline lunr, tanto para criar a indexação quanto para pesquisar. Você pode fazer isso fornecendo um hash pipeline
com nomes de funções e corpo, por exemplo:
activate :search do | search |
search . pipeline = {
tildes : <<-JS
function(token, tokenIndex, tokens) {
return token
.replace('á', 'a')
.replace('é', 'e')
.replace('í', 'i')
.replace('ó', 'o')
.replace('ú', 'u');
}
JS
}
end
Isso registrará a função tildes
no pipeline lunr e a adicionará ao construir o índice. Da documentação do Lunr:
As funções no pipeline são chamadas com três argumentos: o token atual que está sendo processado; o índice desse token na matriz de tokens e toda a lista de tokens que fazem parte do documento que está sendo processado. Isso permite o processamento simples de tokens em unigramas, bem como o processamento mais sofisticado de n-gramas.
A função deve retornar a versão processada do texto, que por sua vez será passada para a próxima função no pipeline. Retornar indefinido impedirá qualquer processamento adicional do token e esse token não chegará ao índice.
Observe que se você adicionar uma função ao pipeline, ela também será carregada ao desserializar o índice, e lunr falhará com um erro Cannot load un-registered function: tildes
se não tiver sido registrado novamente. Você pode registrá-los manualmente ou simplesmente incluir o seguinte em um arquivo .js.erb
para ser executado antes de carregar o índice:
<%= search_lunr_js_pipeline %>
O arquivo de índice gerado contém um objeto JSON com duas propriedades:
index
contém o índice lunr.js serializado, que você pode carregar via lunr.Index.load(lunrData.index)
docs
é um mapa dos IDs de documentos gerados automaticamente para um objeto que contém os atributos configurados para armazenamento Normalmente, você carregará o index
em uma instância de índice lunr e, em seguida, usará o mapa docs
para procurar o valor retornado e apresentá-lo ao usuário.
Você também deve require
o arquivo lunr.min.js
em seu arquivo javascript sprockets principal (se estiver usando o pipeline de ativos) para poder realmente carregar o índice:
//= require lunr.min
Se você estiver usando os recursos i18n do lunr, você também deve carregar os arquivos de suporte e de idioma do Stemmer (nessa ordem) aqui:
//= require lunr.min
//= require lunr.stemmer.support
//= require lunr.es
O pipeline Middleman (se habilitado) não inclui arquivos json
por padrão, mas você pode modificar isso facilmente adicionando .json
à opção exts
das extensões correspondentes, como gzip
e asset_hash
:
activate :asset_hash do | asset_hash |
asset_hash . exts << '.json'
end
Observe que se você executar o arquivo json de índice por meio da extensão hash de ativo, precisará recuperar o URL de destino real ao carregar o arquivo no navegador para pesquisa, usando o auxiliar de visualização search_index_path
:
var lunrIndex = null ;
var lunrData = null ;
// Download index data
$ . ajax ( {
url : "<%= search_index_path %>" ,
cache : true ,
method : 'GET' ,
success : function ( data ) {
lunrData = data ;
lunrIndex = lunr . Index . load ( lunrData . index ) ;
}
} ) ;
Um grande obrigado a:
middleman-alias
, na qual nos baseamos para desenvolver este.middleman-lunrjs
e middleman-lunr
, que serviram de inspiração para a confecção deste.lunr.js