diff options
Diffstat (limited to 'packages/gitbook-plugin-lunr')
-rw-r--r-- | packages/gitbook-plugin-lunr/.gitignore | 31 | ||||
-rw-r--r-- | packages/gitbook-plugin-lunr/.npmignore | 2 | ||||
-rw-r--r-- | packages/gitbook-plugin-lunr/index.js | 99 | ||||
-rw-r--r-- | packages/gitbook-plugin-lunr/package.json | 44 | ||||
-rw-r--r-- | packages/gitbook-plugin-lunr/src/actions.js | 43 | ||||
-rw-r--r-- | packages/gitbook-plugin-lunr/src/index.js | 28 | ||||
-rw-r--r-- | packages/gitbook-plugin-lunr/src/reducer.js | 31 |
7 files changed, 278 insertions, 0 deletions
diff --git a/packages/gitbook-plugin-lunr/.gitignore b/packages/gitbook-plugin-lunr/.gitignore new file mode 100644 index 0000000..7c6f0eb --- /dev/null +++ b/packages/gitbook-plugin-lunr/.gitignore @@ -0,0 +1,31 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# Deployed apps should consider commenting this line out: +# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git +node_modules + +# vim swapfile +*.swp + +# Plugin assets +_assets diff --git a/packages/gitbook-plugin-lunr/.npmignore b/packages/gitbook-plugin-lunr/.npmignore new file mode 100644 index 0000000..7bc36b7 --- /dev/null +++ b/packages/gitbook-plugin-lunr/.npmignore @@ -0,0 +1,2 @@ +# Publish assets on NPM +!_assets diff --git a/packages/gitbook-plugin-lunr/index.js b/packages/gitbook-plugin-lunr/index.js new file mode 100644 index 0000000..bdde8f6 --- /dev/null +++ b/packages/gitbook-plugin-lunr/index.js @@ -0,0 +1,99 @@ +/* eslint-disable no-var, object-shorthand */ +var lunr = require('lunr'); +var Entities = require('html-entities').AllHtmlEntities; + +var Html = new Entities(); + +var searchIndex; + +// Called with the `this` context provided by Gitbook +function getSearchIndex(context) { + if (!searchIndex) { + // Create search index + var ignoreSpecialCharacters = ( + context.config.get('pluginsConfig.lunr.ignoreSpecialCharacters') + || context.config.get('lunr.ignoreSpecialCharacters') + ); + + searchIndex = lunr(function() { + this.ref('url'); + + this.field('title', { boost: 10 }); + this.field('keywords', { boost: 15 }); + this.field('body'); + + if (!ignoreSpecialCharacters) { + // Don't trim non words characters (to allow search such as "C++") + this.pipeline.remove(lunr.trimmer); + } + }); + } + return searchIndex; +} + +// Map of Lunr ref to document +var documentsStore = {}; + +var searchIndexEnabled = true; +var indexSize = 0; + +module.exports = { + hooks: { + // Index each page + 'page': function(page) { + const search = page.attributes.search; + + if (this.output.name != 'website' || !searchIndexEnabled || search === false) { + return page; + } + + var text, maxIndexSize; + maxIndexSize = this.config.get('pluginsConfig.lunr.maxIndexSize') || this.config.get('lunr.maxIndexSize'); + + this.log.debug.ln('index page', page.path); + + text = page.content; + // Decode HTML + text = Html.decode(text); + // Strip HTML tags + text = text.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; + } + + var keywords = []; + if (search) { + keywords = search.keywords || []; + } + + // Add to index + var doc = { + url: this.output.toURL(page.path), + title: page.title, + summary: page.description, + keywords: keywords.join(' '), + body: text + }; + + documentsStore[doc.url] = doc; + getSearchIndex(this).add(doc); + + 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({ + index: getSearchIndex(this), + store: documentsStore + })); + } + } +}; diff --git a/packages/gitbook-plugin-lunr/package.json b/packages/gitbook-plugin-lunr/package.json new file mode 100644 index 0000000..6a26f2d --- /dev/null +++ b/packages/gitbook-plugin-lunr/package.json @@ -0,0 +1,44 @@ +{ + "name": "gitbook-plugin-lunr", + "description": "Static and local index for search in GitBook", + "main": "index.js", + "browser": "./_assets/theme.js", + "version": "4.0.0", + "dependencies": { + "gitbook-core": "4.0.0", + "html-entities": "1.2.0", + "lunr": "0.5.12" + }, + "devDependencies": { + "gitbook-plugin": "4.0.0" + }, + "engines": { + "gitbook": ">=3.0.0" + }, + "gitbook": { + "properties": { + "maxIndexSize": { + "type": "number", + "title": "Limit size for the index", + "default": 1000000 + }, + "ignoreSpecialCharacters": { + "type": "boolean", + "title": "Ignore special characters in words", + "default": false + } + } + }, + "scripts": { + "build-js": "gitbook-plugin build ./src/index.js ./_assets/theme.js", + "prepublish": "npm run build-js" + }, + "homepage": "https://github.com/GitBookIO/gitbook", + "repository": { + "type": "git", + "url": "https://github.com/GitBookIO/gitbook.git" + }, + "bugs": { + "url": "https://github.com/GitBookIO/gitbook/issues" + } +} diff --git a/packages/gitbook-plugin-lunr/src/actions.js b/packages/gitbook-plugin-lunr/src/actions.js new file mode 100644 index 0000000..765fa2e --- /dev/null +++ b/packages/gitbook-plugin-lunr/src/actions.js @@ -0,0 +1,43 @@ +const GitBook = require('gitbook-core'); + +const TYPES = { + LOAD: 'lunr/load' +}; +const INDEX_FILENAME = 'search_index.json'; + +/** + * Load an index set + * @param {JSON} json + * @return {Action} + */ +function load(json) { + return { type: TYPES.LOAD, json }; +} + +/** + * Fetch an index + * @return {Action} + */ +function fetch() { + return (dispatch, getState) => { + const { lunr, file } = getState(); + const { idx } = lunr; + const filePath = file.relative(INDEX_FILENAME); + + if (idx) { + return GitBook.Promise.resolve(); + } + + return GitBook.Promise.resolve() + .then(() => { + return window.fetch(filePath); + }) + .then(response => response.json()) + .then(json => dispatch(load(json))); + }; +} + +module.exports = { + TYPES, + fetch +}; diff --git a/packages/gitbook-plugin-lunr/src/index.js b/packages/gitbook-plugin-lunr/src/index.js new file mode 100644 index 0000000..1135f51 --- /dev/null +++ b/packages/gitbook-plugin-lunr/src/index.js @@ -0,0 +1,28 @@ +const GitBook = require('gitbook-core'); +const reduce = require('./reducer'); +const actions = require('./actions'); + +/** + * Search in the local index + * @param {String} query + * @return {Promise<List>} + */ +function searchHandler(query, dispatch, getState) { + // Fetch the index if non loaded + return dispatch(actions.fetch()) + + // Execute the search + .then(() => { + const { idx, store } = getState().lunr; + const results = idx.search(query); + + return results.map(({ref}) => store.get(ref).toJS()); + }); +} + +module.exports = GitBook.createPlugin({ + activate: (dispatch, getState, { Search }) => { + dispatch(Search.registerHandler('lunr', searchHandler)); + }, + reduce +}); diff --git a/packages/gitbook-plugin-lunr/src/reducer.js b/packages/gitbook-plugin-lunr/src/reducer.js new file mode 100644 index 0000000..7e317c4 --- /dev/null +++ b/packages/gitbook-plugin-lunr/src/reducer.js @@ -0,0 +1,31 @@ +const lunr = require('lunr'); +const GitBook = require('gitbook-core'); +const { Record } = GitBook.Immutable; + +const { TYPES } = require('./actions'); + +/* + We store the lunr index an the document index in the store. + */ + +const LunrState = Record({ + idx: null, + store: {} +}); + +module.exports = GitBook.createReducer('lunr', (state, action) => { + state = state || LunrState(); + + switch (action.type) { + + case TYPES.LOAD: + return state + .set('idx', lunr.Index.load(action.json.index)) + .merge({ + store: action.json.store + }); + + default: + return state; + } +}); |