静态搜索javascript lunr.js


原文链接: 静态搜索javascript lunr.js

A static website with a dynamic search function? Yes. As alternatives to embeddable scripts from Google or other search engines, you can provide your visitors a custom search by indexing your content files directly.

  • GitHub Gist for Hugo Workflow. This gist contains a simple workflow to create a search index for your static website. It uses a simple Grunt script to index all your content files and lunr.js to serve the search results.
  • hugo-lunr. A simple way to add site search to your static Hugo site using lunr.js. Hugo-lunr will create an index file of any html and markdown documents in your Hugo project.
  • hugo-lunr-zh. A bit like Hugo-lunr, but Hugo-lunr-zh can help you separate the Chinese keywords.
  • Github Gist for Fuse.js integration. This gist demonstrates how to leverage Hugo's existing build time processing to generate a searchable JSON index used by Fuse.js on the client side. Although this gist uses Fuse.js for fuzzy matching, any client side search tool capable of reading JSON indexes will work. Does not require npm, grunt or other build-time tools except Hugo!

Commercial Search Services

  • Algolia's Search API makes it easy to deliver a great search experience in your apps and websites. Algolia Search provides hosted full-text, numerical, faceted, and geolocalized search.

var lunrIndex, pagesIndex;

// Initialize lunrjs using our generated index file
function initLunr() {
    // First retrieve the index file
    $.getJSON(baseurl + "/json/search.json")
        .done(function(index) {
            pagesIndex = index;
            // Set up lunrjs by declaring the fields we use
            // Also provide their boost level for the ranking
            lunrIndex = new lunr.Index
            lunrIndex.ref("uri");
            lunrIndex.field('title', {
                boost: 15
            });
            lunrIndex.field('tags', {
                boost: 10
            });
            lunrIndex.field("content", {
                boost: 5
            });

            // Feed lunr with each file and let lunr actually index them
            pagesIndex.forEach(function(page) {
                lunrIndex.add(page);
            });
            lunrIndex.pipeline.remove(lunrIndex.stemmer)
        })
        .fail(function(jqxhr, textStatus, error) {
            var err = textStatus + ", " + error;
            console.error("Error getting Hugo index flie:", err);
        });
}

/**
 * Trigger a search in lunr and transform the result
 *
 * @param  {String} query
 * @return {Array}  results
 */
function search(query) {
    // Find the item in our index corresponding to the lunr one to have more info
    return lunrIndex.search(query).map(function(result) {
            return pagesIndex.filter(function(page) {
                return page.uri === result.ref;
            })[0];
        });
}

// Let's get started
initLunr();
$( document ).ready(function() {
    var horseyList = horsey($("#search-by").get(0), {
        suggestions: function (value, done) {
            var query = $("#search-by").val();
            var results = search(query);
            done(results);
        },
        filter: function (q, suggestion) {
            return true;
        },
        set: function (value) {
            location.href=value.href;
        },
        render: function (li, suggestion) {
            var uri = suggestion.uri.substring(1,suggestion.uri.length);
            var indexOfIndex = uri.lastIndexOf("/index");
            if (indexOfIndex == -1) {
                indexOfIndex = uri.length;
            }
            var href = uri.substring(uri.indexOf("/"), indexOfIndex);
            suggestion.href = baseurl + href;

            var query = $("#search-by").val();
            var numWords = 2;
            var text = suggestion.content.match("(?:\\s?(?:[\\w]+)\\s?){0,"+numWords+"}"+query+"(?:\\s?(?:[\\w]+)\\s?){0,"+numWords+"}");
            suggestion.context = text;
            var image = '<div>' + '» ' + suggestion.title + '</div><div style="font-size:12px">' + (suggestion.context || '') +'</div>';
            li.innerHTML = image;
        },
        limit: 10
    });
    horseyList.refreshPosition();
});
$(document).ready(function () {
    'use strict';
    var resultwindow = $('div.search-result-window');
    var resultlist = $('ul.search-results');
    var noresults = $('.no-results');

    // Set up search
    $.getJSON('/lunr.json', function (response) {
        // Create index
        var index = lunr(function() {
            this.ref('uri');
            this.field('title', { boost: 10 });
            this.field('content');
            this.field('tags');
        });

        $.each(response, function(i, item) {
            index.add(item);
        });

        // Handle search
        $('input#search').on('keyup', function () {
            // Get query
            var query = $(this).val();

            if (query) {
                resultwindow.show();

                // Search for query
                var result = index.search(query);
                console.log(result);

                // Show results
                resultlist.empty();
                if (result.length > 0) {
                    noresults.hide();
                    for (var item in result) {
                        var ref = result[item].ref;
                        var title = response.find(function(item) { return item.uri == ref; }).title;
                        var searchitem = '<li><a href="' + ref + '">' + title + '</a></li>';
                        resultlist.append(searchitem);
                    }
                } else {
                    noresults.show();
                }

            } else {
                resultwindow.hide();
            }
        });
    });
});

function closeSearchWindow() {
    $('div.search-result-window').hide();
    $('input#search').val('');
}
`