summaryrefslogtreecommitdiffstats
path: root/packages/gitbook-core/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'packages/gitbook-core/src/lib')
-rw-r--r--packages/gitbook-core/src/lib/bootstrap.js28
-rw-r--r--packages/gitbook-core/src/lib/composeReducer.js16
-rw-r--r--packages/gitbook-core/src/lib/connect.js13
-rw-r--r--packages/gitbook-core/src/lib/createContext.js52
-rw-r--r--packages/gitbook-core/src/lib/createPlugin.js31
-rw-r--r--packages/gitbook-core/src/lib/createReducer.js27
-rw-r--r--packages/gitbook-core/src/lib/renderWithContext.js25
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;