diff options
Diffstat (limited to 'packages/gitbook-core/src/lib')
-rw-r--r-- | packages/gitbook-core/src/lib/bootstrap.js | 28 | ||||
-rw-r--r-- | packages/gitbook-core/src/lib/composeReducer.js | 16 | ||||
-rw-r--r-- | packages/gitbook-core/src/lib/connect.js | 13 | ||||
-rw-r--r-- | packages/gitbook-core/src/lib/createContext.js | 52 | ||||
-rw-r--r-- | packages/gitbook-core/src/lib/createPlugin.js | 31 | ||||
-rw-r--r-- | packages/gitbook-core/src/lib/createReducer.js | 27 | ||||
-rw-r--r-- | packages/gitbook-core/src/lib/renderWithContext.js | 25 |
7 files changed, 192 insertions, 0 deletions
diff --git a/packages/gitbook-core/src/lib/bootstrap.js b/packages/gitbook-core/src/lib/bootstrap.js new file mode 100644 index 0000000..f5183d1 --- /dev/null +++ b/packages/gitbook-core/src/lib/bootstrap.js @@ -0,0 +1,28 @@ +const ReactDOM = require('react-dom'); + +const getPayload = require('./getPayload'); +const createContext = require('./createContext'); +const renderWithContext = require('./renderWithContext'); + +/** + * Bootstrap GitBook on the browser (this function should not be called on the server side) + */ +function bootstrap() { + const initialState = getPayload(window.document); + const plugins = window.gitbookPlugins; + + const mountNode = document.getElementById('content'); + + // Create the redux store + const context = createContext(plugins, initialState); + + window.gitbookContext = context; + + // Render with the store + const el = renderWithContext(context); + + ReactDOM.render(el, mountNode); +} + + +module.exports = bootstrap; diff --git a/packages/gitbook-core/src/lib/composeReducer.js b/packages/gitbook-core/src/lib/composeReducer.js new file mode 100644 index 0000000..fa2a589 --- /dev/null +++ b/packages/gitbook-core/src/lib/composeReducer.js @@ -0,0 +1,16 @@ + +/** + * Compose multiple reducers into one + * @param {Function} reducers + * @return {Function} + */ +function composeReducer(...reducers) { + return (state, action) => { + return reducers.reduce( + (newState, reducer) => reducer(newState, action), + state + ); + }; +} + +module.exports = composeReducer; diff --git a/packages/gitbook-core/src/lib/connect.js b/packages/gitbook-core/src/lib/connect.js new file mode 100644 index 0000000..e18158e --- /dev/null +++ b/packages/gitbook-core/src/lib/connect.js @@ -0,0 +1,13 @@ +const ReactRedux = require('react-redux'); + +/** + * Connect a component to the GitBook store + * @param {ReactComponent} Component + * @param {Function} mapStateToProps + * @return {ReactComponent} + */ +function connect(Component, mapStateToProps, mapDispatchToProps) { + return ReactRedux.connect(mapStateToProps, mapDispatchToProps)(Component); +} + +module.exports = connect; diff --git a/packages/gitbook-core/src/lib/createContext.js b/packages/gitbook-core/src/lib/createContext.js new file mode 100644 index 0000000..516688e --- /dev/null +++ b/packages/gitbook-core/src/lib/createContext.js @@ -0,0 +1,52 @@ +/* eslint-disable no-console */ +const { Record } = require('immutable'); +const Redux = require('redux'); +const ReduxThunk = require('redux-thunk').default; + +const coreReducers = require('../reducers'); +const composeReducer = require('./composeReducer'); + +const GitBookContext = Record({ + store: null, + actions: {} +}, 'GitBookContext'); + +/** + * Create a new context containing redux store from an initial state and a list of plugins. + * Each plugin entry is the result of {createPlugin}. + * + * @param {Array<Plugin>} plugins + * @param {Object} initialState + * @return {GitBookContext} context + */ +function createContext(plugins, initialState) { + // Compose the reducer from core with plugins + const pluginReducers = plugins.map(plugin => plugin.reduce); + const reducer = composeReducer(...[coreReducers].concat(pluginReducers)); + + // Get actions from all plugins + const actions = plugins.reduce((accu, plugin) => { + return { ...accu, ...plugin.actions }; + }); + + const store = Redux.createStore( + (state, action) => { + console.log('[store]', action.type); + return reducer(state, action); + }, + initialState, + Redux.compose(Redux.applyMiddleware(ReduxThunk)) + ); + + // Initialize the plugins + plugins.forEach(plugin => { + plugin.init(store.dispatch, store.getState); + }); + + return GitBookContext({ + store, + actions + }); +} + +module.exports = createContext; diff --git a/packages/gitbook-core/src/lib/createPlugin.js b/packages/gitbook-core/src/lib/createPlugin.js new file mode 100644 index 0000000..7a49053 --- /dev/null +++ b/packages/gitbook-core/src/lib/createPlugin.js @@ -0,0 +1,31 @@ + +const defaultInit = ((dispatch, getState) => {}); +const defaultReduce = ((state, action) => state); + +/** + * Create a plugin to extend the state and the views. + * + * @param {Function(dispatch, state)} onInitialState + * @param {Funciton(state, action)} onReduceState + * @return {Plugin} + */ +function createPlugin({ init, reduce, actions }) { + init = init || defaultInit; + reduce = reduce || defaultReduce; + actions = actions || {}; + + const plugin = { + init, + reduce, + actions + }; + + if (typeof window !== 'undefined') { + window.gitbookPlugins = window.gitbookPlugins || []; + window.gitbookPlugins.push(plugin); + } + + return plugin; +} + +module.exports = createPlugin; diff --git a/packages/gitbook-core/src/lib/createReducer.js b/packages/gitbook-core/src/lib/createReducer.js new file mode 100644 index 0000000..2ebecfb --- /dev/null +++ b/packages/gitbook-core/src/lib/createReducer.js @@ -0,0 +1,27 @@ + +/** + * Helper to create a reducer that extend the store. + * + * @param {String} property + * @param {Function(state, action): state} reduce + * @return {Function(state, action): state} + */ +function createReducer(name, reduce) { + return (state, action) => { + const value = state[name]; + const newValue = reduce(value, action); + + if (newValue === value) { + return state; + } + + const newState = { + ...state, + [name]: newValue + }; + + return newState; + }; +} + +module.exports = createReducer; diff --git a/packages/gitbook-core/src/lib/renderWithContext.js b/packages/gitbook-core/src/lib/renderWithContext.js new file mode 100644 index 0000000..b9e2cfd --- /dev/null +++ b/packages/gitbook-core/src/lib/renderWithContext.js @@ -0,0 +1,25 @@ +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 + * @param {GitBookContext} context + * @return {React.Element} element + */ +function renderWithContext(context) { + return ( + <Provider store={context.store}> + <PJAXWrapper> + <IntlProvider> + <InjectedComponent matching={{ role: 'Body' }} /> + </IntlProvider> + </PJAXWrapper> + </Provider> + ); +} + +module.exports = renderWithContext; |