gitbook-plugin-search
Advanced tools
Comparing version 1.2.0 to 2.0.0
require([ | ||
"gitbook", | ||
"lodash" | ||
], function(gitbook, _) { | ||
var index = null; | ||
var $searchInput, $searchForm; | ||
'gitbook', | ||
'jquery' | ||
], function(gitbook, $) { | ||
var MAX_RESULTS = 15; | ||
var MAX_DESCRIPTION_SIZE = 500; | ||
// Use a specific index | ||
function loadIndex(data) { | ||
index = lunr.Index.load(data); | ||
} | ||
var usePushState = (typeof history.pushState !== 'undefined'); | ||
// Fetch the search index | ||
function fetchIndex() { | ||
$.getJSON(gitbook.state.basePath+"/search_index.json") | ||
.then(loadIndex); | ||
} | ||
// DOM Elements | ||
var $body = $('body'); | ||
var $bookSearchResults; | ||
var $searchInput; | ||
var $searchList; | ||
var $searchTitle; | ||
var $searchResultsCount; | ||
var $searchQuery; | ||
// Search for a term and return results | ||
function search(q) { | ||
if (!index) return; | ||
// Throttle search | ||
function throttle(fn, wait) { | ||
var timeout; | ||
var results = _.chain(index.search(q)) | ||
.map(function(result) { | ||
var parts = result.ref.split("#") | ||
return { | ||
path: parts[0], | ||
hash: parts[1] | ||
return function() { | ||
var ctx = this, args = arguments; | ||
if (!timeout) { | ||
timeout = setTimeout(function() { | ||
timeout = null; | ||
fn.apply(ctx, args); | ||
}, wait); | ||
} | ||
}) | ||
.value(); | ||
return results; | ||
}; | ||
} | ||
// Create search form | ||
function createForm(value) { | ||
if ($searchForm) $searchForm.remove(); | ||
$searchForm = $('<div>', { | ||
'class': 'book-search', | ||
'role': 'search' | ||
}); | ||
$searchInput = $('<input>', { | ||
'type': 'text', | ||
'class': 'form-control', | ||
'val': value, | ||
'placeholder': 'Type to search' | ||
}); | ||
$searchInput.appendTo($searchForm); | ||
$searchForm.prependTo(gitbook.state.$book.find('.book-summary')); | ||
} | ||
// Return true if search is open | ||
function isSearchOpen() { | ||
return gitbook.state.$book.hasClass("with-search"); | ||
return $body.hasClass('with-search'); | ||
} | ||
@@ -65,72 +43,219 @@ | ||
gitbook.state.$book.toggleClass("with-search", _state); | ||
$body.toggleClass('with-search', _state); | ||
// If search bar is open: focus input | ||
if (isSearchOpen()) { | ||
gitbook.sidebar.toggle(true); | ||
if (gitbook.sidebar) { | ||
gitbook.sidebar.toggle(true); | ||
} | ||
$searchInput.focus(); | ||
} else { | ||
$searchInput.blur(); | ||
$searchInput.val(""); | ||
gitbook.sidebar.filter(null); | ||
$searchInput.val(''); | ||
$bookSearchResults.removeClass('open'); | ||
} | ||
} | ||
// Recover current search when page changed | ||
function recoverSearch() { | ||
var keyword = gitbook.storage.get("keyword", ""); | ||
function displayResults(res) { | ||
$bookSearchResults.addClass('open'); | ||
createForm(keyword); | ||
var noResults = res.count == 0; | ||
$bookSearchResults.toggleClass('no-results', noResults); | ||
if (keyword.length > 0) { | ||
if(!isSearchOpen()) { | ||
toggleSearch(); | ||
// Clear old results | ||
$searchList.empty(); | ||
// Display title for research | ||
$searchResultsCount.text(res.count); | ||
$searchQuery.text(res.query); | ||
// Create an <li> element for each result | ||
res.results.forEach(function(res) { | ||
var $li = $('<li>', { | ||
'class': 'search-results-item' | ||
}); | ||
var $title = $('<h3>'); | ||
var $link = $('<a>', { | ||
'href': gitbook.state.root+res.url, | ||
'text': res.title | ||
}); | ||
var content = res.body.trim(); | ||
if (content.length > MAX_DESCRIPTION_SIZE) { | ||
content = content.slice(0, MAX_DESCRIPTION_SIZE).trim()+'...'; | ||
} | ||
gitbook.sidebar.filter(_.pluck(search(keyword), "path")); | ||
var $content = $('<p>').html(content); | ||
$link.appendTo($title); | ||
$title.appendTo($li); | ||
$content.appendTo($li); | ||
$li.appendTo($searchList); | ||
}); | ||
} | ||
function launchSearch(q) { | ||
// Add class for loading | ||
$body.addClass('search-loading'); | ||
// Launch search query | ||
throttle(gitbook.search.query(q, 0, MAX_RESULTS) | ||
.then(function(results) { | ||
displayResults(results); | ||
}) | ||
.always(function() { | ||
$body.removeClass('search-loading'); | ||
}), 1000); | ||
} | ||
function launchSearchFromQueryString() { | ||
var q = getParameterByName('q'); | ||
if (q && q.length > 0) { | ||
// Toggle search | ||
toggleSearch(true); | ||
// Update search input | ||
$searchInput.val(q); | ||
// Launch search | ||
launchSearch(q); | ||
} | ||
}; | ||
} | ||
function bindSearch() { | ||
// Bind DOM | ||
$searchInput = $('#book-search-input'); | ||
$bookSearchResults = $('#book-search-results'); | ||
$searchList = $bookSearchResults.find('.search-results-list'); | ||
$searchTitle = $bookSearchResults.find('.search-results-title'); | ||
$searchResultsCount = $searchTitle.find('.search-results-count'); | ||
$searchQuery = $searchTitle.find('.search-query'); | ||
gitbook.events.bind("start", function(config) { | ||
// Pre-fetch search index and create the form | ||
fetchIndex(); | ||
createForm(); | ||
// Type in search bar | ||
$(document).on("keyup", ".book-search input", function(e) { | ||
// Detect escape key in search input | ||
$('#book-search-input').on('keyup', function(e) { | ||
var key = (e.keyCode ? e.keyCode : e.which); | ||
var q = $(this).val(); | ||
if (key == 27) { | ||
e.preventDefault(); | ||
toggleSearch(false); | ||
return; | ||
} | ||
}); | ||
// Launch query based on input content | ||
function handleUpdate(element) { | ||
var q = element.val(); | ||
if (q.length == 0) { | ||
gitbook.sidebar.filter(null); | ||
gitbook.storage.remove("keyword"); | ||
} else { | ||
var results = search(q); | ||
gitbook.sidebar.filter( | ||
_.pluck(results, "path") | ||
); | ||
gitbook.storage.set("keyword", q); | ||
$bookSearchResults.removeClass('open'); | ||
} | ||
else { | ||
launchSearch(q); | ||
} | ||
} | ||
// Detect true content change in search input | ||
// Workaround for IE < 9 | ||
var propertyChangeUnbound = false; | ||
$('#book-search-input').on('propertychange', function(e) { | ||
if (e.originalEvent.propertyName == 'value') { | ||
handleUpdate($(this)); | ||
} | ||
}); | ||
// Create the toggle search button | ||
gitbook.toolbar.createButton({ | ||
icon: 'fa fa-search', | ||
label: 'Search', | ||
position: 'left', | ||
onClick: toggleSearch | ||
// HTML5 (IE9 & others) | ||
$('#book-search-input').on('input', function(e) { | ||
// Unbind propertychange event for IE9+ | ||
if (!propertyChangeUnbound) { | ||
$(this).unbind('propertychange'); | ||
propertyChangeUnbound = true; | ||
} | ||
handleUpdate($(this)); | ||
}); | ||
// Push to history on blur | ||
$('#book-search-input').on('blur', function(e) { | ||
// Update history state | ||
if (usePushState) { | ||
var uri = updateQueryString('q', $(this).val()); | ||
history.pushState({ path: uri }, null, uri); | ||
} | ||
}); | ||
toggleSearch(false); | ||
} | ||
gitbook.events.on('start', function() { | ||
// Create the toggle search button | ||
if (gitbook.toolbar) { | ||
gitbook.toolbar.createButton({ | ||
icon: 'fa fa-search', | ||
label: 'Search', | ||
position: 'left', | ||
onClick: toggleSearch | ||
}); | ||
} | ||
// Bind keyboard to toggle search | ||
gitbook.keyboard.bind(['f'], toggleSearch) | ||
if (gitbook.keyboard) { | ||
gitbook.keyboard.bind(['f'], toggleSearch); | ||
} | ||
}); | ||
gitbook.events.bind("page.change", recoverSearch); | ||
gitbook.events.on('page.change', function() { | ||
bindSearch(); | ||
// Launch search based on query parameter | ||
if (gitbook.search.isInitialized) { | ||
launchSearchFromQueryString(); | ||
} | ||
}); | ||
gitbook.events.on('search.ready', function() { | ||
bindSearch(); | ||
// Launch search from query param at start | ||
launchSearchFromQueryString(); | ||
}); | ||
function getParameterByName(name) { | ||
var url = window.location.href; | ||
name = name.replace(/[\[\]]/g, '\\$&'); | ||
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)', 'i'), | ||
results = regex.exec(url); | ||
if (!results) return null; | ||
if (!results[2]) return ''; | ||
return decodeURIComponent(results[2].replace(/\+/g, ' ')); | ||
} | ||
function updateQueryString(key, value) { | ||
value = encodeURIComponent(value); | ||
var url = window.location.href; | ||
var re = new RegExp('([?&])' + key + '=.*?(&|#|$)(.*)', 'gi'), | ||
hash; | ||
if (re.test(url)) { | ||
if (typeof value !== 'undefined' && value !== null) | ||
return url.replace(re, '$1' + key + '=' + value + '$2$3'); | ||
else { | ||
hash = url.split('#'); | ||
url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, ''); | ||
if (typeof hash[1] !== 'undefined' && hash[1] !== null) | ||
url += '#' + hash[1]; | ||
return url; | ||
} | ||
} | ||
else { | ||
if (typeof value !== 'undefined' && value !== null) { | ||
var separator = url.indexOf('?') !== -1 ? '&' : '?'; | ||
hash = url.split('#'); | ||
url = hash[0] + separator + key + '=' + value; | ||
if (typeof hash[1] !== 'undefined' && hash[1] !== null) | ||
url += '#' + hash[1]; | ||
return url; | ||
} | ||
else | ||
return url; | ||
} | ||
} | ||
}); | ||
57
index.js
@@ -1,17 +0,1 @@ | ||
var lunr = require('lunr'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var _ = require('lodash'); | ||
// Create search index | ||
var searchIndex = lunr(function () { | ||
this.ref('url'); | ||
this.field('title', { boost: 10 }); | ||
this.field('body'); | ||
}); | ||
var searchIndexEnabled = true; | ||
var indexSize = 0; | ||
module.exports = { | ||
@@ -21,3 +5,3 @@ book: { | ||
js: [ | ||
'lunr.min.js', 'search.js' | ||
'search-engine.js', 'search.js' | ||
], | ||
@@ -27,43 +11,4 @@ css: [ | ||
] | ||
}, | ||
hooks: { | ||
// Index each page | ||
"page": function(page) { | ||
if (this.output.name != 'website' || !searchIndexEnabled) return page; | ||
var text, maxIndexSize; | ||
maxIndexSize = this.config.get('pluginsConfig.search.maxIndexSize') || this.config.get('search.maxIndexSize'); | ||
this.log.debug.ln('index page', page.path); | ||
// Transform as TEXT | ||
text = page.content.replace(/(<([^>]+)>)/ig, ''); | ||
indexSize = indexSize + text.length; | ||
if (indexSize > maxIndexSize) { | ||
this.log.warn.ln("search index is too big, indexing is now disabled"); | ||
searchIndexEnabled = false; | ||
return page; | ||
} | ||
// Add to index | ||
searchIndex.add({ | ||
url: this.output.toURL(page.path), | ||
title: page.title, | ||
body: text | ||
}); | ||
return page; | ||
}, | ||
// Write index to disk | ||
"finish": function() { | ||
if (this.output.name != 'website') return; | ||
this.log.debug.ln('write search index'); | ||
return this.output.writeFile('search_index.json', JSON.stringify(searchIndex)); | ||
} | ||
} | ||
}; | ||
{ | ||
"name": "gitbook-plugin-search", | ||
"description": "Search content from your book", | ||
"main": "index.js", | ||
"version": "1.2.0", | ||
"engines": { | ||
"gitbook": ">=3.0.0-pre.0" | ||
}, | ||
"dependencies": { | ||
"lunr": "0.5.12", | ||
"lodash": "3.10.1" | ||
}, | ||
"homepage": "https://github.com/GitbookIO/plugin-search", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/GitbookIO/plugin-search.git" | ||
}, | ||
"license": "Apache-2.0", | ||
"bugs": { | ||
"url": "https://github.com/GitbookIO/plugin-search/issues" | ||
}, | ||
"devDependencies": { | ||
"less": "2.5.1" | ||
}, | ||
"scripts": { | ||
"prepublish": "cp node_modules/lunr/lunr.min.js ./assets/lunr.min.js;lessc ./less/search.less > ./assets/search.css" | ||
}, | ||
"gitbook": { | ||
"properties": { | ||
"maxIndexSize": { | ||
"type": "number", | ||
"title": "Limit size for the index", | ||
"default": 1000000 | ||
} | ||
} | ||
} | ||
"name": "gitbook-plugin-search", | ||
"description": "Search input for yoru GitBook", | ||
"main": "index.js", | ||
"version": "2.0.0", | ||
"engines": { | ||
"gitbook": ">=3.0.0-pre.0" | ||
}, | ||
"dependencies": {}, | ||
"homepage": "https://github.com/GitbookIO/plugin-search", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/GitbookIO/plugin-search.git" | ||
}, | ||
"license": "Apache-2.0", | ||
"bugs": { | ||
"url": "https://github.com/GitbookIO/plugin-search/issues" | ||
}, | ||
"devDependencies": { | ||
"eslint": "^2.7.0", | ||
"less": "2.5.1" | ||
}, | ||
"scripts": { | ||
"prepublish": "lessc ./less/search.less > ./assets/search.css" | ||
} | ||
} |
@@ -1,5 +0,7 @@ | ||
# plugin-search | ||
# search | ||
This plugin adds interactive search in sidebar | ||
This plugin is a default plugin for GitBook, it adds an interactive search bar to your book. | ||
This plugin is backend agnostic. | ||
### Disable this plugin | ||
@@ -15,1 +17,8 @@ | ||
### Backends | ||
| Backend | Plugin Name | Description | | ||
| ------- | ----------- | ----------- | | ||
| [Lunr](https://github.com/GitbookIO/plugin-lunr) | `lunr` | Index the content into a local/offlien index | | ||
| [Algolia](https://github.com/GitbookIO/plugin-algolia) | `algolia` | Index the content in Algolia | | ||
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
0
10
333
24
24401
2
1
- Removedlodash@3.10.1
- Removedlunr@0.5.12
- Removedlodash@3.10.1(transitive)
- Removedlunr@0.5.12(transitive)