基于 LunrJS 的 Middleman 搜索。
将此行添加到应用程序的 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
是否在文档结构图中存储该字段(见下文),默认为 falseindex
是否对该字段建立索引,默认为truerequired
如果标记为必填的字段具有空值或 null 值,则资源不会被索引请注意,会自动包含一个特殊字段id
,并使用自动生成的标识符作为文档的ref
。
所有字段值均从资源data
(即其 frontmatter)或resource.metadata
中的options
(即proxy
页面中指定的任何选项)中检索,但以下情况除外:
url
是实际的资源 urlcontent
从渲染资源中提取的文本,不包括其布局然后,您可以通过lunrIndex
对象从 Javascript 查询索引(有关更多信息,请参阅索引文件):
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 改编了我们在 Manas 使用的 lodash v3 代码)
该 gem 包含 MihaiValentin/lunr-languages 提供的替代语言的资源。请参阅该存储库以获取可用语言的列表。
如果您想使用未包含的语言,请在项目的文件夹中设置lunr.yourlang.js
文件,并将该文件夹添加到lunr_dirs
中,以便 gem 知道在哪里查找它。
您可以通过定义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
这将在 lunr 管道中注册tildes
函数,并在构建索引时添加它。来自 Lunr 文档:
使用三个参数调用管道中的函数:正在处理的当前令牌;该标记在标记数组中的索引,以及正在处理的文档的标记部分的整个列表。这使得能够对标记进行简单的一元语法处理以及更复杂的 n 元语法处理。
该函数应返回文本的处理版本,该版本将依次传递给管道中的下一个函数。返回未定义将阻止对令牌的任何进一步处理,并且该令牌将不会进入索引。
请注意,如果您向管道添加函数,则在反序列化索引时也会加载该函数,并且 lunr 将失败,并出现Cannot load un-registered function: tildes
错误(如果尚未重新注册)。您可以手动注册它们,也可以简单地将以下内容包含在要在加载索引之前执行的.js.erb
文件中:
<%= search_lunr_js_pipeline %>
生成的索引文件包含一个具有两个属性的 JSON 对象:
index
包含序列化的 lunr.js 索引,您可以通过lunr.Index.load(lunrData.index)
加载该索引docs
是从自动生成的文档 ID 到包含配置为存储的属性的对象的映射您通常会将index
加载到 lunr 索引实例中,然后使用docs
映射查找返回值并将其呈现给用户。
您还应该require
主链轮 JavaScript 文件中的lunr.min.js
文件(如果使用资产管道)才能实际加载索引:
//= 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 文件,则在浏览器中加载文件进行搜索时,您将需要使用search_index_path
视图助手来检索实际的目标 URL:
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
贡献者