Recherche Middleman basée sur LunrJS.
Ajoutez cette ligne au Gemfile de votre application :
gem 'middleman-search'
Et puis exécutez :
$ bundle
Ou installez-le vous-même en tant que :
$ gem install middleman-search
Vous devez activer le module dans votre config.rb
, indiquant à l'extension comment indexer vos ressources :
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
Où resources
est une liste du début de l'URL des ressources à indexer (testé avec String#start_with?
), index_path
est le chemin relatif du fichier d'index généré sur votre site et fields
est un hachage avec une entrée pour chaque champ. à indexer, avec un hachage d'options associées :
boost
Spécifie un boost de pertinence lunr lors de la recherche dans ce champstore
S'il faut stocker ce champ dans l'explorateur de documents (voir ci-dessous), la valeur par défaut est falseindex
S'il faut indexer ce champ, la valeur par défaut est truerequired
La ressource ne sera pas indexée si un champ marqué comme obligatoire a une valeur vide ou nulle Notez qu'un id
de champ spécial est inclus automatiquement, avec un identifiant généré automatiquement à utiliser comme ref
du document.
Toutes les valeurs des champs sont récupérées à partir des data
de ressource (c'est-à-dire de leur contenu) ou des options
du fichier resource.metadata
(c'est-à-dire toute option spécifiée dans une page proxy
), à l'exception de :
url
qui est l'URL réelle de la ressourcecontent
le texte extrait de la ressource rendue, sans inclure sa mise en page Vous pouvez ensuite interroger l'index depuis Javascript via l'objet lunrIndex
(voir Fichier d'index pour plus d'informations) :
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 ] ) ;
}
} ) ;
(Merci @Jeepler d'avoir adapté le code lodash v3 que nous utilisions à Manas)
Ce joyau comprend des ressources pour des langues alternatives fournies par MihaiValentin/lunr-linguals. Veuillez vous référer à ce référentiel pour une liste des langues disponibles.
Si vous souhaitez travailler avec une langue qui n'est pas incluse, configurez un fichier lunr.yourlang.js
dans un dossier de votre projet et ajoutez ce dossier à lunr_dirs
afin que la gemme sache où le chercher.
Vous pouvez entièrement personnaliser le contenu à indexer et stocker par ressource en définissant un rappel 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
Cette option accepte un rappel qui sera exécuté pour chaque ressource, et sera exécuté avec le document à indexer et la carte à stocker, dans les objets index
et docs
de la sortie respectivement (voir ci-dessous), ainsi qu'avec la ressource en cours de traitement. Vous pouvez utiliser ce rappel pour modifier l'un ou l'autre, ou throw(:skip)
pour ignorer la ressource en question.
Dans certains cas, vous souhaiterez peut-être ajouter une nouvelle fonction au pipeline lunr, à la fois pour créer l'indexation et ensuite pour la recherche. Vous pouvez le faire en fournissant un hachage pipeline
avec les noms et le corps des fonctions, par exemple :
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
Cela enregistrera la fonction tildes
dans le pipeline lunr et l'ajoutera lors de la construction de l'index. Extrait de la documentation Lunr :
Les fonctions du pipeline sont appelées avec trois arguments : le jeton en cours de traitement ; l'index de ce jeton dans le tableau de jetons et la liste complète des jetons faisant partie du document en cours de traitement. Cela permet un traitement unigramme simple des jetons ainsi qu'un traitement n-gramme plus sophistiqué.
La fonction doit renvoyer la version traitée du texte, qui sera à son tour transmise à la fonction suivante du pipeline. Le retour d'undefined empêchera tout traitement ultérieur du jeton, et ce jeton ne parviendra pas à l'index.
Notez que si vous ajoutez une fonction au pipeline, elle sera également chargée lors de la désérialisation de l'index, et lunr échouera avec une erreur Cannot load un-registered function: tildes
si elle n'a pas été réenregistrée. Vous pouvez soit les enregistrer manuellement, soit simplement inclure les éléments suivants dans un fichier .js.erb
à exécuter avant de charger l'index :
<%= search_lunr_js_pipeline %>
Le fichier d'index généré contient un objet JSON avec deux propriétés :
index
contient l'index lunr.js sérialisé, que vous pouvez charger via lunr.Index.load(lunrData.index)
docs
est une carte des identifiants de document générés automatiquement vers un objet qui contient les attributs configurés pour le stockage Vous chargerez généralement l' index
dans une instance d'index lunr, puis utiliserez la carte docs
pour rechercher la valeur renvoyée et la présenter à l'utilisateur.
Vous devez également require
le fichier lunr.min.js
dans votre fichier javascript principal de sprockets (si vous utilisez le pipeline d'actifs) pour pouvoir réellement charger l'index :
//= require lunr.min
Si vous utilisez les fonctionnalités i18n de Lunr, vous devez également charger les fichiers de support et de langue de Stemmer (dans cet ordre) ici :
//= require lunr.min
//= require lunr.stemmer.support
//= require lunr.es
Le pipeline Middleman (s'il est activé) n'inclut pas les fichiers json
par défaut, mais vous pouvez facilement modifier cela en ajoutant .json
à l'option exts
des extensions correspondantes, telles que gzip
et asset_hash
:
activate :asset_hash do | asset_hash |
asset_hash . exts << '.json'
end
Notez que si vous exécutez le fichier d'index json via l'extension de hachage d'actif, vous devrez récupérer l'URL de destination réelle lors du chargement du fichier dans le navigateur pour la recherche, à l'aide de l'assistant de vue 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 ) ;
}
} ) ;
Un grand merci à :
middleman-alias
, sur laquelle nous nous sommes basés pour développer celle-ci.middleman-lunrjs
et middleman-lunr
, qui ont servi d'inspiration pour réaliser celui-ci.lunr.js