Поиск посредника на основе LunrJS.
Добавьте эту строку в Gemfile вашего приложения:
gem 'middleman-search'
И затем выполните:
$ bundle
Или установите его самостоятельно как:
$ gem install middleman-search
Вам необходимо активировать модуль в вашем config.rb
, указав расширению, как индексировать ваши ресурсы:
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
Где resources
— это список начала URL-адресов индексируемых ресурсов (проверено с помощью String#start_with?
), index_path
— это относительный путь к сгенерированному индексному файлу на вашем сайте, а fields
— это хэш с одной записью для каждого поля. для индексации, с хешем связанных опций:
boost
Указывает повышение релевантности lunr при поиске в этом поле.store
Сохранять ли это поле в карте документа (см. ниже), по умолчанию — false.index
Индексировать ли это поле, по умолчанию — truerequired
Ресурс не будет проиндексирован, если поле, помеченное как обязательное, имеет пустое или нулевое значение. Обратите внимание, что специальный id
поля добавляется автоматически, а автоматически сгенерированный идентификатор будет использоваться в качестве ref
на документ.
Значения всех полей извлекаются из data
ресурса (т. е. из его заголовка) или из options
в resource.metadata
(т. е. из любых параметров, указанных на proxy
странице), за исключением:
url
, который является фактическим URL-адресом ресурсаcontent
текст, извлеченный из визуализированного ресурса, без включения его макета. Затем вы можете запросить индекс из Javascript через объект lunrIndex
(дополнительную информацию см. в файле индекса):
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 ] ) ;
}
} ) ;
(Спасибо @Jeepler за адаптацию кода lodash v3, который мы использовали в Манасе)
Этот драгоценный камень включает ресурсы для альтернативных языков, предоставленные MihaiValentin/lunr-languages. Пожалуйста, обратитесь к этому репозиторию за списком доступных языков.
Если вы хотите работать с языком, который не включен, создайте файл lunr.yourlang.js
в папке вашего проекта и добавьте эту папку в lunr_dirs
чтобы гем знал, где его искать.
Вы можете полностью настроить индексируемый и сохраняемый контент для каждого ресурса, определив обратный вызов 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
Эта опция принимает обратный вызов, который будет выполняться для каждого ресурса и будет выполняться с индексируемым документом и картой, которая будет сохранена, в объектах index
и docs
выходных данных соответственно (см. ниже), а также в ресурсе. обрабатываются. Вы можете использовать этот обратный вызов, чтобы изменить любой из них, или throw(:skip)
чтобы пропустить рассматриваемый ресурс.
В некоторых случаях вам может потребоваться добавить новую функцию в конвейер lunr как для создания индексации, так и для поиска. Вы можете сделать это, предоставив хеш pipeline
с именами и телом функций, например:
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
Это зарегистрирует функцию tildes
в конвейере lunr и добавит ее при построении индекса. Из документации Лунра:
Функции в конвейере вызываются с тремя аргументами: текущий обрабатываемый токен; индекс этого токена в массиве токенов и весь список токенов, являющийся частью обрабатываемого документа. Это обеспечивает простую обработку токенов униграмм, а также более сложную обработку н-грамм.
Функция должна возвращать обработанную версию текста, которая, в свою очередь, будет передана следующей функции в конвейере. Возврат неопределенного значения предотвратит дальнейшую обработку токена, и этот токен не попадет в индекс.
Обратите внимание: если вы добавите функцию в конвейер, она также будет загружена при десериализации индекса, и lunr завершится с ошибкой Cannot load un-registered function: tildes
если она не была перерегистрирована. Вы можете зарегистрировать их вручную или просто включить следующее в файл .js.erb
, который будет выполняться перед загрузкой индекса:
<%= search_lunr_js_pipeline %>
Сгенерированный индексный файл содержит объект JSON с двумя свойствами:
index
содержит сериализованный индекс lunr.js, который вы можете загрузить через lunr.Index.load(lunrData.index)
docs
— это сопоставление автоматически сгенерированных идентификаторов документов с объектом, содержащим атрибуты, настроенные для хранения. Обычно вы загружаете index
в экземпляр индекса lunr, а затем используете карту docs
для поиска возвращаемого значения и представления его пользователю.
Вам также require
файл lunr.min.js
в вашем основном файле javascript sprockets (при использовании конвейера ресурсов), чтобы иметь возможность фактически загружать индекс:
//= require lunr.min
Если вы используете возможности lunr i18n, вам также следует загрузить сюда файлы поддержки и языка Stemmer (в указанном порядке):
//= require lunr.min
//= require lunr.stemmer.support
//= require lunr.es
Конвейер Middleman (если он включен) по умолчанию не включает файлы json
, но вы можете легко изменить это, добавив .json
к опции exts
соответствующих расширений, таких как gzip
и asset_hash
:
activate :asset_hash do | asset_hash |
asset_hash . exts << '.json'
end
Обратите внимание: если вы запускаете индексный json-файл через расширение хэша актива, вам нужно будет получить фактический целевой URL-адрес при загрузке файла в браузер для поиска, используя помощник представления 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 ) ;
}
} ) ;
Большое спасибо:
middleman-alias
, на котором мы основывались при разработке этого расширения.middleman-lunrjs
и middleman-lunr
, которые послужили вдохновением для создания этого.lunr.js