diff options
Diffstat (limited to 'packages/gitbook-core/src/actions')
-rw-r--r-- | packages/gitbook-core/src/actions/TYPES.js | 16 | ||||
-rw-r--r-- | packages/gitbook-core/src/actions/components.js | 37 | ||||
-rw-r--r-- | packages/gitbook-core/src/actions/history.js | 188 | ||||
-rw-r--r-- | packages/gitbook-core/src/actions/i18n.js | 33 |
4 files changed, 274 insertions, 0 deletions
diff --git a/packages/gitbook-core/src/actions/TYPES.js b/packages/gitbook-core/src/actions/TYPES.js new file mode 100644 index 0000000..9876057 --- /dev/null +++ b/packages/gitbook-core/src/actions/TYPES.js @@ -0,0 +1,16 @@ + +module.exports = { + // Components + REGISTER_COMPONENT: 'components/register', + UNREGISTER_COMPONENT: 'components/unregister', + // Navigation + HISTORY_ACTIVATE: 'history/activate', + HISTORY_DEACTIVATE: 'history/deactivate', + HISTORY_LISTEN: 'history/listen', + HISTORY_UPDATE: 'history/update', + PAGE_FETCH_START: 'history/fetch:start', + PAGE_FETCH_END: 'history/fetch:end', + PAGE_FETCH_ERROR: 'history/fetch:error', + // i18n + I18N_REGISTER_LOCALE: 'i18n/register:locale' +}; diff --git a/packages/gitbook-core/src/actions/components.js b/packages/gitbook-core/src/actions/components.js new file mode 100644 index 0000000..f21c382 --- /dev/null +++ b/packages/gitbook-core/src/actions/components.js @@ -0,0 +1,37 @@ +const ACTION_TYPES = require('./TYPES'); + +/** + * Find all components matching a descriptor + * @param {List<ComponentDescriptor>} state + * @param {String} matching.role + */ +function findMatchingComponents(state, matching) { + return state + .filter(({descriptor}) => { + if (matching.role && matching.role !== descriptor.role) { + return false; + } + + return true; + }) + .map(component => component.Component); +} + +/** + * Register a new component + * @param {React.Class} Component + * @param {Descriptor} descriptor + * @return {Action} + */ +function registerComponent(Component, descriptor) { + return { + type: ACTION_TYPES.REGISTER_COMPONENT, + Component, + descriptor + }; +} + +module.exports = { + findMatchingComponents, + registerComponent +}; diff --git a/packages/gitbook-core/src/actions/history.js b/packages/gitbook-core/src/actions/history.js new file mode 100644 index 0000000..1c33f4a --- /dev/null +++ b/packages/gitbook-core/src/actions/history.js @@ -0,0 +1,188 @@ +const ACTION_TYPES = require('./TYPES'); +const getPayload = require('../lib/getPayload'); +const Location = require('../models/Location'); + +const SUPPORTED = ( + typeof window !== 'undefined' && + window.history && window.history.pushState && window.history.replaceState && + // pushState isn't reliable on iOS until 5. + !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/) +); + +/** + * Initialize the history + */ +function activate() { + return (dispatch, getState) => { + dispatch({ + type: ACTION_TYPES.HISTORY_ACTIVATE, + listener: (location) => { + location = Location.fromNative(location); + const prevLocation = getState().history.location; + + // Fetch page if required + if (!prevLocation || location.pathname !== prevLocation.pathname) { + dispatch(fetchPage(location.pathname)); + } + + // Signal location to listener + dispatch(emit()); + + // Update the location + dispatch({ + type: ACTION_TYPES.HISTORY_UPDATE, + location + }); + } + }); + + // Trigger for existing listeners + dispatch(emit()); + }; +} + +/** + * Emit current location + * @param {List|Array<Function>} to? + */ +function emit(to) { + return (dispatch, getState) => { + const { listeners, client } = getState().history; + + if (!client) { + return; + } + + const location = Location.fromNative(client.location); + + to = to || listeners; + + to.forEach(handler => { + handler(location, dispatch, getState); + }); + }; +} + +/** + * Cleanup the history + */ +function deactivate() { + return { type: ACTION_TYPES.HISTORY_DEACTIVATE }; +} + +/** + * Push a new url into the history + * @param {String|Location} location + * @return {Action} action + */ +function push(location) { + return (dispatch, getState) => { + const { client } = getState().history; + location = Location.fromNative(location); + + if (SUPPORTED) { + client.push(location.toNative()); + } else { + redirect(location.toString()); + } + }; +} + +/** + * Replace current state in history + * @param {String|Location} location + * @return {Action} action + */ +function replace(location) { + return (dispatch, getState) => { + const { client } = getState().history; + location = Location.fromNative(location); + + if (SUPPORTED) { + client.replace(location.toNative()); + } else { + redirect(location.toString()); + } + }; +} + +/** + * Hard redirection + * @param {String} uri + * @return {Action} action + */ +function redirect(uri) { + return () => { + window.location.href = uri; + }; +} + +/** + * Listen to url change + * @param {Function} listener + * @return {Action} action + */ +function listen(listener) { + return (dispatch, getState) => { + dispatch({ type: ACTION_TYPES.HISTORY_LISTEN, listener }); + + // Trigger for existing listeners + dispatch(emit([ listener ])); + }; +} + +/** + * Fetch a new page and update the store accordingly + * @param {String} pathname + * @return {Action} action + */ +function fetchPage(pathname) { + return (dispatch, getState) => { + dispatch({ type: ACTION_TYPES.PAGE_FETCH_START }); + + window.fetch(pathname, { + credentials: 'include' + }) + .then( + response => { + return response.text(); + } + ) + .then( + html => { + const payload = getPayload(html); + + if (!payload) { + throw new Error('No payload found in page'); + } + + dispatch({ type: ACTION_TYPES.PAGE_FETCH_END, payload }); + } + ) + .catch( + error => { + // dispatch(redirect(pathname)); + dispatch({ type: ACTION_TYPES.PAGE_FETCH_ERROR, error }); + } + ); + }; +} + +/** + * Fetch a new article + * @param {SummaryArticle} article + * @return {Action} action + */ +function fetchArticle(article) { + return fetchPage(article.path); +} + +module.exports = { + activate, + deactivate, + listen, + push, + replace, + fetchPage, + fetchArticle +}; diff --git a/packages/gitbook-core/src/actions/i18n.js b/packages/gitbook-core/src/actions/i18n.js new file mode 100644 index 0000000..115c5a1 --- /dev/null +++ b/packages/gitbook-core/src/actions/i18n.js @@ -0,0 +1,33 @@ +const ACTION_TYPES = require('./TYPES'); + +/** + * Register messages for a locale + * @param {String} locale + * @param {Map<String:String>} messages + * @return {Action} + */ +function registerLocale(locale, messages) { + return { type: ACTION_TYPES.I18N_REGISTER_LOCALE, locale, messages }; +} + +/** + * Register multiple locales + * @param {Map<String:Object>} locales + * @return {Action} + */ +function registerLocales(locales) { + return (dispatch) => { + for (const locale in locales) { + if (!locales.hasOwnProperty(locale)) { + continue; + } + + dispatch(registerLocale(locale, locales[locale])); + } + }; +} + +module.exports = { + registerLocale, + registerLocales +}; |