Start search plugin

This commit is contained in:
Samy Pesse
2016-09-28 18:14:35 +02:00
parent 26fc021b90
commit 287c80b2e1
16 changed files with 245 additions and 78 deletions
+2
View File
@@ -4,6 +4,7 @@
"description": "Core for GitBook plugins API",
"main": "./lib/index.js",
"dependencies": {
"bluebird": "^3.4.6",
"classnames": "^2.2.5",
"html-tags": "^1.1.1",
"immutable": "^3.8.1",
@@ -11,6 +12,7 @@
"react-dom": "^15.3.1",
"react-helmet": "^3.1.0",
"react-immutable-proptypes": "^2.1.0",
"react-intl": "^2.1.5",
"react-redux": "^4.4.5",
"react-safe-html": "^0.3.0",
"redux": "^3.5.2",
@@ -0,0 +1,22 @@
const React = require('react');
const intl = require('react-intl');
const ReactRedux = require('react-redux');
const IntlProvider = React.createClass({
propTypes: {
children: React.PropTypes.node
},
render() {
// TODO
const messages = {};
return (
<intl.IntlProvider locale={'en'} messages={messages}>
{this.props.children}
</intl.IntlProvider>
);
}
});
module.exports = ReactRedux.connect()(IntlProvider);
+8 -2
View File
@@ -1,5 +1,7 @@
const React = require('react');
const Immutable = require('immutable');
const Head = require('react-helmet');
const Promise = require('bluebird');
const { Provider } = require('react-redux');
const { Flex, Box } = require('reflexbox');
@@ -9,6 +11,7 @@ const HTMLContent = require('./components/HTMLContent');
const Link = require('./components/Link');
const Icon = require('./components/Icon');
const Button = require('./components/Button');
const IntlProvider = require('./components/IntlProvider');
const { registerComponent } = require('./actions/components');
const ACTIONS = require('./actions/TYPES');
@@ -46,7 +49,10 @@ module.exports = {
Link,
Icon,
Button,
React,
// Utilities
Shapes
Shapes,
// Librairies
React,
Immutable,
Promise
};
+5 -1
View File
@@ -1,7 +1,9 @@
const React = require('react');
const { Provider } = require('react-redux');
const { InjectedComponent } = require('./components/InjectedComponent');
const PJAXWrapper = require('./components/PJAXWrapper');
const IntlProvider = require('./components/IntlProvider');
/**
* Render the application for a store
@@ -12,7 +14,9 @@ function renderWithStore(store) {
return (
<Provider store={store}>
<PJAXWrapper>
<InjectedComponent matching={{ role: 'Body' }} />
<IntlProvider>
<InjectedComponent matching={{ role: 'Body' }} />
</IntlProvider>
</PJAXWrapper>
</Provider>
);
@@ -0,0 +1,24 @@
{
"name": "gitbook-plugin-search",
"description": "Search integration in GitBook",
"main": "index.js",
"version": "2.0.0",
"dependencies": {
"gitbook-core": "^0.0.0"
},
"devDependencies": {
"gitbook-plugin": "*"
},
"engines": {
"gitbook": ">=3.0.0"
},
"homepage": "https://github.com/GitbookIO/gitbook",
"repository": {
"type": "git",
"url": "https://github.com/GitbookIO/gitbook.git"
},
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/GitbookIO/gitbook/issues"
}
}
@@ -0,0 +1,49 @@
const { Promise, Immutable } = require('gitbook-core');
const { List } = Immutable;
const TYPES = require('./types');
/**
* Start a search query
* @param {String} q
* @return {Action}
*/
function query(q) {
return (dispatch, getState) => {
const handlers = getState().search;
dispatch({ type: TYPES.UPDATE_QUERY, query: q });
return Promise.reduce(handlers, (results, handler) => {
return Promise(handler(q))
.then(handlerResults => results.concat(handlerResults));
}, List())
.then(results => {
dispatch({ type: TYPES.UPDATE_RESULTS, query: q });
});
};
}
/**
* Register a search handler
* @param {String} name
* @param {Function} handler
* @return {Action}
*/
function registerHandler(name, handler) {
return { type: TYPES.REGISTER_HANDLER, name, handler };
}
/**
* Unregister a search handler
* @param {String} name
* @return {Action}
*/
function unregisterHandler(name) {
return { type: TYPES.UNREGISTER_HANDLER, name };
}
module.exports = {
query,
registerHandler,
unregisterHandler
};
@@ -0,0 +1,7 @@
module.exports = {
REGISTER_HANDLER: 'search/register_handler',
UNREGISTER_HANDLER: 'search/unregister_handler',
UPDATE_QUERY: 'search/update_query',
UPDATE_RESULTS: 'search/update_results'
};
@@ -0,0 +1,47 @@
const GitBook = require('gitbook-core');
const { React } = GitBook;
const search = require('../actions/search');
const DEBOUNCE_MS = 600;
const SearchInput = React.createClass({
propTypes: {
dispatch: React.PropTypes.func
},
onUpdateQuery(q) {
const { dispatch } = this.props;
dispatch(search.query(q));
},
onKeyDown(event) {
const { value } = event.currentTarget;
if (this.debouncedSearch) {
clearTimeout(this.debouncedSearch);
}
this.debouncedSearch = setTimeout(() => {
this.debouncedSearch = null;
this.onUpdateQuery(value);
}, DEBOUNCE_MS);
},
componentWillUnmount() {
if (this.debouncedSearch) {
clearTimeout(this.debouncedSearch);
}
},
render() {
return (
<div className="Search/Input">
<input type="text" placeholder="" onKeyDown={this.onKeyDown} />
</div>
);
}
});
module.exports = GitBook.connect(SearchInput);
@@ -0,0 +1,28 @@
const GitBook = require('gitbook-core');
const { React } = GitBook;
const SearchResults = React.createClass({
propTypes: {
results: GitBook.Shapes.list
},
render() {
const { results } = this.props;
return (
<div className="Search/Results">
{results.map(result => {
})}
</div>
);
}
});
function mapStateToProps(state) {
return {
results: state.search.results
};
}
module.exports = GitBook.connect(SearchResults, mapStateToProps);
@@ -0,0 +1,13 @@
const GitBook = require('gitbook-core');
const SearchInput = require('./components/Input');
const SearchResults = require('./components/Results');
const reducers = require('./reducers');
module.exports = GitBook.createPlugin(
(dispatch, state) => {
dispatch(GitBook.registerComponent(SearchInput, { role: 'search:input' }));
dispatch(GitBook.registerComponent(SearchResults, { role: 'search:results' }));
},
reducers
);
@@ -0,0 +1,3 @@
const GitBook = require('gitbook-core');
module.exports = GitBook.createReducer('search', require('./search'));
@@ -0,0 +1,37 @@
const GitBook = require('gitbook-core');
const { Record, List, OrderedMap } = GitBook.Immutable;
const TYPES = require('../actions/types');
const Result = Record({
url: String(''),
title: String(''),
body: String('')
});
const SearchState = Record({
// Current query
query: String(''),
// Current list of results
results: List(),
// Search handlers
handlers: OrderedMap()
});
module.exports = (state = SearchState(), action) => {
switch (action.type) {
case TYPES.REGISTER_HANDLER:
return state.merge({
handlers: state.handlers.set(action.name, action.handler)
});
case TYPES.UNREGISTER_HANDLER:
return state.merge({
handlers: state.handlers.remove(action.name)
});
default:
return state;
}
};
@@ -1,52 +0,0 @@
{
"name": "gitbook-plugin-sharing",
"description": "Sharing buttons in GitBooks website",
"main": "index.js",
"version": "1.0.2",
"dependencies": {
"gitbook-core": "^0.0.0",
"react": "^15.3.1"
},
"devDependencies": {
"gitbook-plugin": "*"
},
"engines": {
"gitbook": ">=3.0.0"
},
"homepage": "https://github.com/GitbookIO/plugin-sharing",
"repository": {
"type": "git",
"url": "https://github.com/GitbookIO/plugin-sharing.git"
},
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/GitbookIO/plugin-sharing/issues"
},
"gitbook": {
"properties": {
"facebook": { "type": "boolean", "default": true, "title": "Facebook" },
"twitter": { "type": "boolean", "default": true, "title": "Twitter" },
"google": { "type": "boolean", "default": false, "title": "Google" },
"weibo": { "type": "boolean", "default": false, "description": "Weibo" },
"instapaper": { "type": "boolean", "default": false, "description": "Instapaper" },
"vk": { "type": "boolean", "default": false, "description": "VK" },
"all": {
"type": "array",
"items": {
"type": "string"
},
"default": [
"facebook",
"google",
"twitter",
"weibo",
"instapaper"
],
"uniqueItems": true
}
}
},
"devDependencies": {
"eslint": "^2.7.0"
}
}
@@ -1,17 +0,0 @@
const React = require('react');
const GitBook = require('gitbook-core');
const ShareButton = React.createClass({
render() {
return (
<button>Share</button>
);
}
});
function mapStateToProps(state) {
}
module.exports = GitBook.connect(ShareButton, mapStateToProps);
@@ -1,6 +0,0 @@
const GitBook = require('gitbook-core');
const ShareButton = require('./Button');
module.exports = GitBook.createPlugin((dispatch, state) => {
dispatch(GitBook.registerComponent(ShareButton, { role: 'Toolbar:ActionButton' }));
});