summaryrefslogtreecommitdiffstats
path: root/packages/gitbook-plugin-lunr
diff options
context:
space:
mode:
Diffstat (limited to 'packages/gitbook-plugin-lunr')
-rw-r--r--packages/gitbook-plugin-lunr/.gitignore31
-rw-r--r--packages/gitbook-plugin-lunr/.npmignore2
-rw-r--r--packages/gitbook-plugin-lunr/index.js99
-rw-r--r--packages/gitbook-plugin-lunr/package.json44
-rw-r--r--packages/gitbook-plugin-lunr/src/actions.js43
-rw-r--r--packages/gitbook-plugin-lunr/src/index.js28
-rw-r--r--packages/gitbook-plugin-lunr/src/reducer.js31
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;
+ }
+});