summaryrefslogtreecommitdiffstats
path: root/packages/gitbook-core/src/actions
diff options
context:
space:
mode:
Diffstat (limited to 'packages/gitbook-core/src/actions')
-rw-r--r--packages/gitbook-core/src/actions/TYPES.js16
-rw-r--r--packages/gitbook-core/src/actions/components.js37
-rw-r--r--packages/gitbook-core/src/actions/history.js188
-rw-r--r--packages/gitbook-core/src/actions/i18n.js33
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
+};