gitbook-plugin-search-plus
Advanced tools
Comparing version
require([ | ||
'gitbook', | ||
'jquery' | ||
], function(gitbook, $) { | ||
var MAX_DESCRIPTION_SIZE = 500; | ||
var state = gitbook.state; | ||
var INDEX_DATA = {}; | ||
var usePushState = (typeof history.pushState !== 'undefined'); | ||
'gitbook', | ||
'jquery' | ||
], function (gitbook, $) { | ||
var MAX_DESCRIPTION_SIZE = 500 | ||
var state = gitbook.state | ||
var INDEX_DATA = {} | ||
var usePushState = (typeof history.pushState !== 'undefined') | ||
// DOM Elements | ||
var $body = $('body'); | ||
var $bookSearchResults; | ||
var $searchList; | ||
var $searchTitle; | ||
var $searchResultsCount; | ||
var $searchQuery; | ||
var $body = $('body') | ||
var $bookSearchResults | ||
var $searchList | ||
var $searchTitle | ||
var $searchResultsCount | ||
var $searchQuery | ||
// Throttle search | ||
function throttle(fn, wait) { | ||
var timeout; | ||
function throttle (fn, wait) { | ||
var timeout | ||
return function() { | ||
var ctx = this, | ||
args = arguments; | ||
if (!timeout) { | ||
timeout = setTimeout(function() { | ||
timeout = null; | ||
fn.apply(ctx, args); | ||
}, wait); | ||
} | ||
}; | ||
return function () { | ||
var ctx = this, | ||
args = arguments | ||
if (!timeout) { | ||
timeout = setTimeout(function () { | ||
timeout = null | ||
fn.apply(ctx, args) | ||
}, wait) | ||
} | ||
} | ||
} | ||
function displayResults(res) { | ||
$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'); | ||
function displayResults (res) { | ||
$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') | ||
$bookSearchResults.addClass('open'); | ||
$bookSearchResults.addClass('open') | ||
var noResults = res.count == 0; | ||
$bookSearchResults.toggleClass('no-results', noResults); | ||
var noResults = res.count == 0 | ||
$bookSearchResults.toggleClass('no-results', noResults) | ||
// Clear old results | ||
$searchList.empty(); | ||
$searchList.empty() | ||
// Display title for research | ||
$searchResultsCount.text(res.count); | ||
$searchQuery.text(res.query); | ||
$searchResultsCount.text(res.count) | ||
$searchQuery.text(res.query) | ||
// Create an <li> element for each result | ||
res.results.forEach(function(item) { | ||
var $li = $('<li>', { | ||
'class': 'search-results-item' | ||
}); | ||
res.results.forEach(function (item) { | ||
var $li = $('<li>', { | ||
'class': 'search-results-item' | ||
}) | ||
var $title = $('<h3>'); | ||
var $title = $('<h3>') | ||
var $link = $('<a>', { | ||
'href': gitbook.state.basePath + '/' + item.url + '?h=' + encodeURIComponent(res.query), | ||
'text': item.title, | ||
'data-is-search': 1 | ||
}); | ||
var $link = $('<a>', { | ||
'href': gitbook.state.basePath + '/' + item.url + '?h=' + encodeURIComponent(res.query), | ||
'text': item.title, | ||
'data-is-search': 1 | ||
}) | ||
if ($link[0].href.split('?')[0] === location.href.split('?')[0]) { | ||
$link[0].setAttribute('data-need-reload', 1); | ||
} | ||
if ($link[0].href.split('?')[0] === location.href.split('?')[0]) { | ||
$link[0].setAttribute('data-need-reload', 1) | ||
} | ||
var content = item.body.trim(); | ||
if (content.length > MAX_DESCRIPTION_SIZE) { | ||
content = content + '...'; | ||
} | ||
var $content = $('<p>').html(content); | ||
var content = item.body.trim() | ||
if (content.length > MAX_DESCRIPTION_SIZE) { | ||
content = content + '...' | ||
} | ||
var $content = $('<p>').html(content) | ||
$link.appendTo($title); | ||
$title.appendTo($li); | ||
$content.appendTo($li); | ||
$li.appendTo($searchList); | ||
}); | ||
$('.body-inner').scrollTop(0); | ||
} | ||
$link.appendTo($title) | ||
$title.appendTo($li) | ||
$content.appendTo($li) | ||
$li.appendTo($searchList) | ||
}) | ||
$('.body-inner').scrollTop(0) | ||
} | ||
function escapeRegExp(keyword) { | ||
//escape regexp prevserve word | ||
return String(keyword).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); | ||
} | ||
function escapeRegExp (keyword) { | ||
// escape regexp prevserve word | ||
return String(keyword).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1') | ||
} | ||
function query(keyword) { | ||
if (keyword == null || keyword.trim() === '') return; | ||
function query (keyword) { | ||
if (keyword == null || keyword.trim() === '') return | ||
var results = [], | ||
index = -1; | ||
for (var page in INDEX_DATA) { | ||
if ((index = INDEX_DATA[page].body.toLowerCase().indexOf(keyword.toLowerCase())) !== -1) { | ||
results.push({ | ||
url: page, | ||
title: INDEX_DATA[page].title, | ||
body: INDEX_DATA[page].body.substr(Math.max(0, index - 50), MAX_DESCRIPTION_SIZE) | ||
.replace(/^[^\s,.]+./,'').replace(/(..*)[\s,.].*/, '$1') //prevent break word | ||
var results = [], | ||
index = -1 | ||
for (var page in INDEX_DATA) { | ||
if ((index = INDEX_DATA[page].body.toLowerCase().indexOf(keyword.toLowerCase())) !== -1) { | ||
results.push({ | ||
url: page, | ||
title: INDEX_DATA[page].title, | ||
body: INDEX_DATA[page].body.substr(Math.max(0, index - 50), MAX_DESCRIPTION_SIZE) | ||
.replace(/^[^\s,.]+./, '').replace(/(..*)[\s,.].*/, '$1') // prevent break word | ||
.replace(new RegExp('(' + escapeRegExp(keyword) + ')', 'gi'), '<span class="search-highlight-keyword">$1</span>') | ||
}); | ||
} | ||
} | ||
displayResults({ | ||
count: results.length, | ||
query: keyword, | ||
results: results | ||
}); | ||
}) | ||
} | ||
} | ||
displayResults({ | ||
count: results.length, | ||
query: keyword, | ||
results: results | ||
}) | ||
} | ||
function launchSearch(keyword) { | ||
function launchSearch (keyword) { | ||
// Add class for loading | ||
$body.addClass('with-search'); | ||
$body.addClass('search-loading'); | ||
$body.addClass('with-search') | ||
$body.addClass('search-loading') | ||
function doSearch() { | ||
query(keyword); | ||
$body.removeClass('search-loading'); | ||
} | ||
throttle(doSearch)(); | ||
function doSearch () { | ||
query(keyword) | ||
$body.removeClass('search-loading') | ||
} | ||
function closeSearch() { | ||
$body.removeClass('with-search'); | ||
$('#book-search-results').removeClass('open'); | ||
} | ||
throttle(doSearch)() | ||
} | ||
function bindSearch() { | ||
function closeSearch () { | ||
$body.removeClass('with-search') | ||
$('#book-search-results').removeClass('open') | ||
} | ||
function bindSearch () { | ||
// Bind DOM | ||
var $body = $('body'); | ||
var $body = $('body') | ||
// Launch query based on input content | ||
function handleUpdate() { | ||
var $searchInput = $('#book-search-input input'); | ||
var keyword = $searchInput.val(); | ||
function handleUpdate () { | ||
var $searchInput = $('#book-search-input input') | ||
var keyword = $searchInput.val() | ||
if (keyword.length == 0) { | ||
closeSearch(); | ||
} else { | ||
launchSearch(keyword); | ||
} | ||
if (keyword.length == 0) { | ||
closeSearch() | ||
} else { | ||
launchSearch(keyword) | ||
} | ||
} | ||
$body.on('keyup', '#book-search-input input', function (e) { | ||
if (e.keyCode === 13) { | ||
if (usePushState) { | ||
var uri = updateQueryString('q', $(this).val()) | ||
history.pushState({ | ||
path: uri | ||
}, null, uri) | ||
} | ||
} | ||
handleUpdate() | ||
}) | ||
$body.on('keyup', '#book-search-input input', function(e) { | ||
if (e.keyCode === 13) { | ||
if (usePushState) { | ||
var uri = updateQueryString('q', $(this).val()); | ||
history.pushState({ | ||
path: uri | ||
}, null, uri); | ||
} | ||
} | ||
handleUpdate(); | ||
}); | ||
// Push to history on blur | ||
$body.on('blur', '#book-search-input input', function(e) { | ||
$body.on('blur', '#book-search-input input', function (e) { | ||
// Update history state | ||
if (usePushState) { | ||
var uri = updateQueryString('q', $(this).val()); | ||
history.pushState({ | ||
path: uri | ||
}, null, uri); | ||
} | ||
}); | ||
} | ||
if (usePushState) { | ||
var uri = updateQueryString('q', $(this).val()) | ||
history.pushState({ | ||
path: uri | ||
}, null, uri) | ||
} | ||
}) | ||
} | ||
gitbook.events.on('start', function() { | ||
bindSearch(); | ||
$.getJSON(state.basePath + "/search_plus_index.json").then(function(data) { | ||
INDEX_DATA = data; | ||
showResult(); | ||
closeSearch(); | ||
}); | ||
}); | ||
gitbook.events.on('start', function () { | ||
bindSearch() | ||
$.getJSON(state.basePath + '/search_plus_index.json').then(function (data) { | ||
INDEX_DATA = data | ||
showResult() | ||
closeSearch() | ||
}) | ||
}) | ||
// 高亮文本 | ||
var highLightPageInner = function(keyword) { | ||
$('.page-inner').mark(keyword, { | ||
'ignoreJoiners': true, | ||
'acrossElements': true, | ||
'separateWordSearch': false | ||
}); | ||
var highLightPageInner = function (keyword) { | ||
$('.page-inner').mark(keyword, { | ||
'ignoreJoiners': true, | ||
'acrossElements': true, | ||
'separateWordSearch': false | ||
}) | ||
setTimeout(function() { | ||
var mark = $('mark[data-markjs="true"]'); | ||
if (mark.length) { | ||
mark[0].scrollIntoView(); | ||
} | ||
}, 100); | ||
}; | ||
setTimeout(function () { | ||
var mark = $('mark[data-markjs="true"]') | ||
if (mark.length) { | ||
mark[0].scrollIntoView() | ||
} | ||
}, 100) | ||
} | ||
function showResult() { | ||
var keyword, type; | ||
if (/\b(q|h)=([^&]+)/.test(location.search)) { | ||
type = RegExp.$1; | ||
keyword = decodeURIComponent(RegExp.$2); | ||
if (type === 'q') { | ||
launchSearch(keyword); | ||
} else { | ||
highLightPageInner(keyword); | ||
} | ||
$('#book-search-input input').val(keyword); | ||
} | ||
function showResult () { | ||
var keyword, type | ||
if (/\b(q|h)=([^&]+)/.test(location.search)) { | ||
type = RegExp.$1 | ||
keyword = decodeURIComponent(RegExp.$2) | ||
if (type === 'q') { | ||
launchSearch(keyword) | ||
} else { | ||
highLightPageInner(keyword) | ||
} | ||
$('#book-search-input input').val(keyword) | ||
} | ||
} | ||
gitbook.events.on('page.change', showResult); | ||
gitbook.events.on('page.change', showResult) | ||
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 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); | ||
function updateQueryString (key, value) { | ||
value = encodeURIComponent(value) | ||
var url = window.location.href.replace(/([?&])(?:q|h)=([^&]+)(&|$)/, function(all, pre, value, end) { | ||
if (end === '&') { | ||
return pre; | ||
} | ||
return ''; | ||
}); | ||
var re = new RegExp('([?&])' + key + '=.*?(&|#|$)(.*)', 'gi'), | ||
hash; | ||
var url = window.location.href.replace(/([?&])(?:q|h)=([^&]+)(&|$)/, function (all, pre, value, end) { | ||
if (end === '&') { | ||
return pre | ||
} | ||
return '' | ||
}) | ||
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; | ||
} | ||
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 } | ||
} | ||
window.addEventListener('click', function(e) { | ||
if (e.target.tagName === 'A' && e.target.getAttribute('data-need-reload')) { | ||
setTimeout(function() { | ||
location.reload(); | ||
}, 100); | ||
} | ||
}, true); | ||
}); | ||
} | ||
window.addEventListener('click', function (e) { | ||
if (e.target.tagName === 'A' && e.target.getAttribute('data-need-reload')) { | ||
setTimeout(function () { | ||
location.reload() | ||
}, 100) | ||
} | ||
}, true) | ||
}) |
100
index.js
@@ -1,64 +0,64 @@ | ||
var Entities = require('html-entities').AllHtmlEntities; | ||
var Entities = require('html-entities').AllHtmlEntities | ||
var Html = new Entities(); | ||
var Html = new Entities() | ||
// Map of Lunr ref to document | ||
var documentsStore = {}; | ||
var documentsStore = { } | ||
module.exports = { | ||
book: { | ||
assets: './assets', | ||
js: [ | ||
'jquery.mark.min.js', | ||
'search.js' | ||
], | ||
css: [ | ||
'search.css' | ||
] | ||
}, | ||
book: { | ||
assets: './assets', | ||
js: [ | ||
'jquery.mark.min.js', | ||
'search.js' | ||
], | ||
css: [ | ||
'search.css' | ||
] | ||
}, | ||
hooks: { | ||
// Index each page | ||
'page': function(page) { | ||
if (this.output.name != 'website' || page.search === false) { | ||
return page; | ||
} | ||
hooks: { | ||
// Index each page | ||
'page': function (page) { | ||
if (this.output.name !== 'website' || page.search === false) { | ||
return page | ||
} | ||
var text; | ||
this.log.debug.ln('index page', page.path); | ||
var text | ||
text = page.content; | ||
// Decode HTML | ||
text = Html.decode(text); | ||
// Strip HTML tags | ||
text = text.replace(/(<([^>]+)>)/ig, ''); | ||
text = text.replace(/[\n ]+/g, ' '); | ||
var keywords = []; | ||
if (page.search) { | ||
keywords = page.search.keywords || []; | ||
} | ||
this.log.debug.ln('index page', page.path) | ||
// Add to index | ||
var doc = { | ||
url: this.output.toURL(page.path), | ||
title: page.title, | ||
summary: page.description, | ||
keywords: keywords.join(' '), | ||
body: text | ||
}; | ||
text = page.content | ||
// Decode HTML | ||
text = Html.decode(text) | ||
// Strip HTML tags | ||
text = text.replace(/(<([^>]+)>)/ig, '') | ||
text = text.replace(/[\n ]+/g, ' ') | ||
var keywords = [] | ||
if (page.search) { | ||
keywords = page.search.keywords || [] | ||
} | ||
documentsStore[doc.url] = doc; | ||
// Add to index | ||
var doc = { | ||
url: this.output.toURL(page.path), | ||
title: page.title, | ||
summary: page.description, | ||
keywords: keywords.join(' '), | ||
body: text | ||
} | ||
return page; | ||
}, | ||
documentsStore[doc.url] = doc | ||
// Write index to disk | ||
'finish': function() { | ||
if (this.output.name != 'website') return; | ||
return page | ||
}, | ||
this.log.debug.ln('write search index'); | ||
return this.output.writeFile('search_plus_index.json', JSON.stringify(documentsStore)); | ||
} | ||
// Write index to disk | ||
'finish': function () { | ||
if (this.output.name !== 'website') return | ||
this.log.debug.ln('write search index') | ||
return this.output.writeFile('search_plus_index.json', JSON.stringify(documentsStore)) | ||
} | ||
}; | ||
} | ||
} |
{ | ||
"name": "gitbook-plugin-search-plus", | ||
"version": "1.0.0", | ||
"version": "1.0.2", | ||
"description": "gitbook powerful search plugin", | ||
@@ -10,2 +10,3 @@ "main": "index.js", | ||
"add": "git add -A", | ||
"standard": "standard --fix assets/search.js, index.js", | ||
"pages:build": "cd examples&&npm install&&npm run build", | ||
@@ -25,6 +26,11 @@ "pages:push": "git subtree --prefix=examples push pages gh-pages" | ||
"devDependencies": { | ||
"pre-commit": "^1.2.2" | ||
"pre-commit": "^1.2.2", | ||
"standard": "^9.0.2" | ||
}, | ||
"pre-commit": { | ||
"run": ["pages:build", "add"], | ||
"run": [ | ||
"standard", | ||
"pages:build", | ||
"add" | ||
], | ||
"silent": true | ||
@@ -31,0 +37,0 @@ }, |
# gitbook-search-plus | ||
This plugin is a powerful search plugin for GitBook. | ||
Search plus. | ||
With it You can search `any characters` in your gitbook document. | ||
### Features | ||
* Search any character | ||
* Search across element (for search code) | ||
* Remember search url | ||
### Use this plugin | ||
@@ -23,5 +27,5 @@ | ||
[](https://lwdgit.github.io/gitbook-plugin-search-plus/) | ||
[](https://lwdgit.github.io/gitbook-plugin-search-plus/) | ||
[](https://lwdgit.github.io/gitbook-plugin-search-plus/book/?q=%E8%BF%99%E6%9C%AC%E5%B0%8F%E4%B9%A6%E7%9A%84%E7%9B%AE%E7%9A%84%E6%98%AF%E5%BC%95%E5%AF%BC%E4%BD%A0%E8%BF%9B%E5%85%A5%20React%20%E5%92%8C%20Webpack%20%E7%9A%84%E4%B8%96%E7%95%8C) | ||
[](https://lwdgit.github.io/gitbook-plugin-search-plus/) | ||
[](https://lwdgit.github.io/gitbook-plugin-search-plus/) | ||
[](https://lwdgit.github.io/gitbook-plugin-search-plus/book/?q=%E8%BF%99%E6%9C%AC%E5%B0%8F%E4%B9%A6%E7%9A%84%E7%9B%AE%E7%9A%84%E6%98%AF%E5%BC%95%E5%AF%BC%E4%BD%A0%E8%BF%9B%E5%85%A5%20React%20%E5%92%8C%20Webpack%20%E7%9A%84%E4%B8%96%E7%95%8C) | ||
@@ -28,0 +32,0 @@ |
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
346
6.46%48
9.09%2953426
-0.03%2
100%1
Infinity%