diff options
Diffstat (limited to 'packages')
22 files changed, 247 insertions, 105 deletions
diff --git a/packages/gitbook-core/src/components/ContextProvider.js b/packages/gitbook-core/src/components/ContextProvider.js index 9b81e9b..86c8d41 100644 --- a/packages/gitbook-core/src/components/ContextProvider.js +++ b/packages/gitbook-core/src/components/ContextProvider.js @@ -1,25 +1,27 @@ const React = require('react'); const { Provider } = require('react-redux'); +const ContextShape = require('../shapes/Context'); + /** * React component to provide a GitBook context to children components. */ const ContextProvider = React.createClass({ propTypes: { - context: React.PropTypes.object.isRequired, + context: ContextShape.isRequired, children: React.PropTypes.node }, childContextTypes: { - gitbookContext: React.PropTypes.object.isRequired + gitbook: ContextShape }, getChildContext() { const { context } = this.props; return { - gitbookContext: context + gitbook: context }; }, diff --git a/packages/gitbook-core/src/components/I18nProvider.js b/packages/gitbook-core/src/components/I18nProvider.js index 8e169c4..32fa4a0 100644 --- a/packages/gitbook-core/src/components/I18nProvider.js +++ b/packages/gitbook-core/src/components/I18nProvider.js @@ -19,4 +19,8 @@ const I18nProvider = React.createClass({ } }); -module.exports = ReactRedux.connect()(I18nProvider); +const mapStateToProps = state => { + return { messages: state.i18n.messages }; +}; + +module.exports = ReactRedux.connect(mapStateToProps)(I18nProvider); diff --git a/packages/gitbook-core/src/components/Link.js b/packages/gitbook-core/src/components/Link.js index 83ecdd5..8c142ea 100644 --- a/packages/gitbook-core/src/components/Link.js +++ b/packages/gitbook-core/src/components/Link.js @@ -1,8 +1,10 @@ const React = require('react'); const ReactRedux = require('react-redux'); -const path = require('path'); -const url = require('url'); + +const File = require('../models/File'); +const SummaryArticle = require('../models/SummaryArticle'); const SummaryArticleShape = require('../shapes/SummaryArticle'); +const ContextShape = require('../shapes/Context'); const Link = React.createClass({ propTypes: { @@ -14,25 +16,31 @@ const Link = React.createClass({ ]) }, + contextTypes: { + gitbook: ContextShape.isRequired + }, + getHref() { - const { to, href } = this.props; + const { gitbook } = this.context; + let { to, href } = this.props; if (href) { return href; } - if (typeof to === 'string') { - return to; + if (SummaryArticle.is(to)) { + return to.toURL(gitbook); } - // Article - if (typeof to.ref === 'string') { - const parts = url.parse(to.ref); - const ext = path.extname(parts.pathname); - const pathname = path.basename(parts.pathname, ext) + '.html'; + if (typeof to === 'string') { + to = new File(to); + } - return pathname + (parts.hash || ''); + if (File.is(to)) { + return to.toURL(gitbook); } + + throw new Error('Invalid format for prop "to"'); }, render() { diff --git a/packages/gitbook-core/src/index.js b/packages/gitbook-core/src/index.js index 4823680..d51d073 100644 --- a/packages/gitbook-core/src/index.js +++ b/packages/gitbook-core/src/index.js @@ -15,7 +15,6 @@ const Icon = require('./components/Icon'); const Button = require('./components/Button'); const I18nProvider = require('./components/I18nProvider'); -const { registerComponent } = require('./actions/components'); const ACTIONS = require('./actions/TYPES'); const Shapes = require('./shapes'); @@ -36,7 +35,6 @@ module.exports = { createReducer, createContext, composeReducer, - registerComponent, // React Components I18nProvider, InjectedComponent, diff --git a/packages/gitbook-core/src/lib/connect.js b/packages/gitbook-core/src/lib/connect.js index e1b267e..2f2a212 100644 --- a/packages/gitbook-core/src/lib/connect.js +++ b/packages/gitbook-core/src/lib/connect.js @@ -2,6 +2,8 @@ const React = require('react'); const ReactRedux = require('react-redux'); const { injectIntl } = require('react-intl'); +const ContextShape = require('../shapes/Context'); + /** * Use the GitBook context provided by ContextProvider to map actions to props * @param {ReactComponent} Component @@ -20,13 +22,13 @@ function connectToActions(Component, mapActionsToProps) { }, contextTypes: { - gitbookContext: React.PropTypes.object.isRequired + gitbook: ContextShape.isRequired }, render() { - const { gitbookContext } = this.context; + const { gitbook } = this.context; const { children, ...props } = this.props; - const { actions, store } = gitbookContext; + const { actions, store } = gitbook; const actionsProps = mapActionsToProps(actions, store.dispatch); diff --git a/packages/gitbook-core/src/lib/createContext.js b/packages/gitbook-core/src/lib/createContext.js index fdc0e0c..1b834e4 100644 --- a/packages/gitbook-core/src/lib/createContext.js +++ b/packages/gitbook-core/src/lib/createContext.js @@ -1,15 +1,22 @@ /* eslint-disable no-console */ -const { Record } = require('immutable'); const Redux = require('redux'); const ReduxThunk = require('redux-thunk').default; +const Plugin = require('./models/Plugin'); +const Context = require('./models/Context'); const coreReducers = require('../reducers'); const composeReducer = require('./composeReducer'); -const GitBookContext = Record({ - store: null, - actions: {} -}, 'GitBookContext'); +const Components = require('./actions/components'); +const I18n = require('./actions/i18n'); +const Navigation = require('./actions/navigation'); + +const corePlugin = Plugin({ + reduce: coreReducers, + actions: { + Components, I18n, Navigation + } +}); /** * Create a new context containing redux store from an initial state and a list of plugins. @@ -17,12 +24,14 @@ const GitBookContext = Record({ * * @param {Array<Plugin>} plugins * @param {Object} initialState - * @return {GitBookContext} context + * @return {Context} context */ function createContext(plugins, initialState) { + plugins = [corePlugin].concat(plugins); + // Compose the reducer from core with plugins const pluginReducers = plugins.map(plugin => plugin.reduce); - const reducer = composeReducer(...[coreReducers].concat(pluginReducers)); + const reducer = composeReducer(pluginReducers); // Get actions from all plugins const actions = plugins.reduce((accu, plugin) => { @@ -43,7 +52,7 @@ function createContext(plugins, initialState) { plugin.init(store.dispatch, store.getState, actions); }); - return GitBookContext({ + return Context({ store, actions }); diff --git a/packages/gitbook-core/src/lib/createPlugin.js b/packages/gitbook-core/src/lib/createPlugin.js index 7a49053..f03bb94 100644 --- a/packages/gitbook-core/src/lib/createPlugin.js +++ b/packages/gitbook-core/src/lib/createPlugin.js @@ -1,24 +1,19 @@ - -const defaultInit = ((dispatch, getState) => {}); -const defaultReduce = ((state, action) => state); +const Plugin = require('../models/Plugin'); /** * Create a plugin to extend the state and the views. * - * @param {Function(dispatch, state)} onInitialState - * @param {Funciton(state, action)} onReduceState + * @param {Function(dispatch, state)} plugin.init + * @param {Function(state, action)} plugin.reduce + * @param {Object} plugin.actions * @return {Plugin} */ function createPlugin({ init, reduce, actions }) { - init = init || defaultInit; - reduce = reduce || defaultReduce; - actions = actions || {}; - - const plugin = { + const plugin = Plugin({ init, reduce, actions - }; + }); if (typeof window !== 'undefined') { window.gitbookPlugins = window.gitbookPlugins || []; diff --git a/packages/gitbook-core/src/models/Context.js b/packages/gitbook-core/src/models/Context.js new file mode 100644 index 0000000..fa68bd8 --- /dev/null +++ b/packages/gitbook-core/src/models/Context.js @@ -0,0 +1,29 @@ +const { Record } = require('immutable'); + +const DEFAULTS = { + store: null, + actions: {} +}; + +class Context extends Record(DEFAULTS) { + + /** + * Return current state + * @return {Object} + */ + getState() { + const { store } = this; + return store.getState(); + } + + /** + * Dispatch an action + * @param {Action} action + */ + dispatch(action) { + const { store } = this; + return store.dispatch(action); + } +} + +module.exports = Context; diff --git a/packages/gitbook-core/src/models/File.js b/packages/gitbook-core/src/models/File.js new file mode 100644 index 0000000..09dfc1b --- /dev/null +++ b/packages/gitbook-core/src/models/File.js @@ -0,0 +1,43 @@ +const path = require('path'); +const { Record } = require('immutable'); + +const DEFAULTS = { + type: '', + mtime: '', + path: '' +}; + +class File extends Record(DEFAULTS) { + constructor(file) { + if (typeof file === 'string') { + file = { path: file }; + } + + super(file); + } + + /** + * Return url for a file in a GitBook context. + * @param {Context} context + * @return {String} url + */ + toURL(context) { + const { file } = context.getState(); + + return path.relative( + path.dirname(file.path), + this.path + ); + } + + static is(file) { + return (file instanceof File); + } + + static create(file) { + return file instanceof File ? + file : new File(file); + } +} + +module.exports = File; diff --git a/packages/gitbook-core/src/models/Plugin.js b/packages/gitbook-core/src/models/Plugin.js new file mode 100644 index 0000000..0654f85 --- /dev/null +++ b/packages/gitbook-core/src/models/Plugin.js @@ -0,0 +1,13 @@ +const { Record } = require('immutable'); + +const DEFAULTS = { + init: ((dispatch, getState) => {}), + reduce: ((state, action) => state), + actions: {} +}; + +class Plugin extends Record(DEFAULTS) { + +} + +module.exports = Plugin; diff --git a/packages/gitbook-core/src/models/SummaryArticle.js b/packages/gitbook-core/src/models/SummaryArticle.js new file mode 100644 index 0000000..b36fbe3 --- /dev/null +++ b/packages/gitbook-core/src/models/SummaryArticle.js @@ -0,0 +1,57 @@ +const url = require('url'); +const path = require('path'); +const { Record, List } = require('immutable'); +const File = require('./File'); + +const OUTPUT_EXTENSION = '.html'; + +const DEFAULTS = { + title: '', + depth: 0, + path: '', + ref: '', + level: '', + articles: List() +}; + +class SummaryArticle extends Record(DEFAULTS) { + constructor(article) { + super({ + ...article, + articles: (new List(article.articles)) + .map(art => new SummaryArticle(art)) + }); + } + + /** + * Return url for a file in a GitBook context. + * @param {Context} context + * @return {String} url + */ + toURL(context) { + const { readme } = context.getState(); + const fileReadme = readme.file; + const parts = url.parse(this.ref); + + if (parts.protocol) { + return this.ref; + } + + const file = new File(parts.pathname); + let filePath = file.toURL(context); + + // Change extension and resolve to .html + if ( + path.basename(filePath, path.extname(filePath)) == 'README' || + (fileReadme && filePath == fileReadme.path) + ) { + filePath = path.join(path.dirname(filePath), 'index' + OUTPUT_EXTENSION); + } else { + filePath = path.basename(filePath, path.extname(filePath)) + OUTPUT_EXTENSION; + } + + return filePath + (parts.hash || ''); + } +} + +module.exports = SummaryArticle; diff --git a/packages/gitbook-core/src/models/SummaryPart.js b/packages/gitbook-core/src/models/SummaryPart.js new file mode 100644 index 0000000..89c76d4 --- /dev/null +++ b/packages/gitbook-core/src/models/SummaryPart.js @@ -0,0 +1,17 @@ +const { Record, List } = require('immutable'); +const SummaryArticle = require('./SummaryArticle'); + +class SummaryPart extends Record({ + title: '', + articles: List() +}) { + constructor(state) { + super({ + ...state, + articles: (new List(state.articles)) + .map(article => new SummaryArticle(article)) + }); + } +} + +module.exports = SummaryPart; diff --git a/packages/gitbook-core/src/reducers/file.js b/packages/gitbook-core/src/reducers/file.js deleted file mode 100644 index 028afc6..0000000 --- a/packages/gitbook-core/src/reducers/file.js +++ /dev/null @@ -1,16 +0,0 @@ -const { Record } = require('immutable'); - -const DEFAULTS = { - type: '', - mtime: '', - path: '' -}; - -class FileState extends Record(DEFAULTS) { - static create(state) { - return state instanceof FileState ? - state : new FileState(state); - } -} - -module.exports = FileState; diff --git a/packages/gitbook-core/src/reducers/readme.js b/packages/gitbook-core/src/reducers/readme.js index 8e99f3d..d88f9ec 100644 --- a/packages/gitbook-core/src/reducers/readme.js +++ b/packages/gitbook-core/src/reducers/readme.js @@ -1,12 +1,12 @@ const { Record } = require('immutable'); -const FileState = require('./file'); +const File = require('../models/file'); class ReadmeState extends Record({ - file: new FileState() + file: new File() }) { constructor(state = {}) { super({ - file: new FileState(state.file) + file: new File(state.file) }); } diff --git a/packages/gitbook-core/src/reducers/summary.js b/packages/gitbook-core/src/reducers/summary.js index 0179ecc..60568ef 100644 --- a/packages/gitbook-core/src/reducers/summary.js +++ b/packages/gitbook-core/src/reducers/summary.js @@ -1,45 +1,17 @@ const { Record, List } = require('immutable'); -const FileState = require('./file'); -class SummaryArticle extends Record({ - title: '', - depth: 0, - path: '', - ref: '', - level: '', - articles: List() -}) { - constructor(state) { - super({ - ...state, - articles: (new List(state.articles)) - .map(article => new SummaryArticle(article)) - }); - } -} - -class SummaryPart extends Record({ - title: '', - articles: List() -}) { - constructor(state) { - super({ - ...state, - articles: (new List(state.articles)) - .map(article => new SummaryArticle(article)) - }); - } -} +const File = require('../models/File'); +const SummaryPart = require('../models/SummaryPart'); class SummaryState extends Record({ - file: new FileState(), + file: new File(), parts: List() }) { constructor(state = {}) { super({ ...state, - file: new FileState(state.file), + file: new File(state.file), parts: (new List(state.parts)) .map(article => new SummaryPart(article)) }); diff --git a/packages/gitbook-core/src/shapes/Context.js b/packages/gitbook-core/src/shapes/Context.js new file mode 100644 index 0000000..dd6d010 --- /dev/null +++ b/packages/gitbook-core/src/shapes/Context.js @@ -0,0 +1,11 @@ +const React = require('react'); +const { + object, + shape +} = React.PropTypes; + + +module.exports = shape({ + store: object, + actions: object +}); diff --git a/packages/gitbook-core/src/shapes/index.js b/packages/gitbook-core/src/shapes/index.js index 59b1735..c372c25 100644 --- a/packages/gitbook-core/src/shapes/index.js +++ b/packages/gitbook-core/src/shapes/index.js @@ -5,6 +5,7 @@ module.exports = { ...ImmutablePropTypes, dispatch: React.PropTypes.func, i18n: require('./i18n'), + Context: require('./Context'), Page: require('./Page'), File: require('./File'), Summary: require('./Summary'), diff --git a/packages/gitbook-plugin-hints/src/index.js b/packages/gitbook-plugin-hints/src/index.js index 0d1c152..2356995 100644 --- a/packages/gitbook-plugin-hints/src/index.js +++ b/packages/gitbook-plugin-hints/src/index.js @@ -34,7 +34,7 @@ const HintAlert = React.createClass({ }); module.exports = GitBook.createPlugin({ - init: (dispatch, getState) => { - dispatch(GitBook.registerComponent(HintAlert, { role: 'block:hint' })); + init: (dispatch, getState, { Components }) => { + dispatch(Components.registerComponent(HintAlert, { role: 'block:hint' })); } }); diff --git a/packages/gitbook-plugin-lunr/src/index.js b/packages/gitbook-plugin-lunr/src/index.js index 16caf96..0eb6e04 100644 --- a/packages/gitbook-plugin-lunr/src/index.js +++ b/packages/gitbook-plugin-lunr/src/index.js @@ -13,9 +13,8 @@ function searchHandler(query) { } module.exports = GitBook.createPlugin({ - init: (dispatch, getState, actions) => { - const { search } = actions; - dispatch(search.registerHandler('lunr', searchHandler)); + init: (dispatch, getState, { Search }) => { + dispatch(Search.registerHandler('lunr', searchHandler)); }, reduce: (state, action) => state }); diff --git a/packages/gitbook-plugin-search/src/index.js b/packages/gitbook-plugin-search/src/index.js index c3b0253..f08d5d6 100644 --- a/packages/gitbook-plugin-search/src/index.js +++ b/packages/gitbook-plugin-search/src/index.js @@ -3,15 +3,15 @@ const GitBook = require('gitbook-core'); const SearchInput = require('./components/Input'); const SearchResults = require('./components/Results'); const reducers = require('./reducers'); -const search = require('./actions/search'); +const Search = require('./actions/search'); module.exports = GitBook.createPlugin({ - init: (dispatch, getState) => { - dispatch(GitBook.registerComponent(SearchInput, { role: 'search:input' })); - dispatch(GitBook.registerComponent(SearchResults, { role: 'search:results' })); + init: (dispatch, getState, { Components }) => { + dispatch(Components.registerComponent(SearchInput, { role: 'search:input' })); + dispatch(Components.registerComponent(SearchResults, { role: 'search:results' })); }, reduce: reducers, actions: { - search + Search } }); diff --git a/packages/gitbook-plugin-theme-default/src/index.js b/packages/gitbook-plugin-theme-default/src/index.js index 9d328f2..2f1a336 100644 --- a/packages/gitbook-plugin-theme-default/src/index.js +++ b/packages/gitbook-plugin-theme-default/src/index.js @@ -49,8 +49,8 @@ ThemeBody = GitBook.connect(ThemeBody, ({page, summary, sidebar}) => { }); module.exports = GitBook.createPlugin({ - init: (dispatch, state) => { - dispatch(GitBook.registerComponent(ThemeBody, { role: 'Body' })); + init: (dispatch, state, { Components }) => { + dispatch(Components.registerComponent(ThemeBody, { role: 'Body' })); }, reduce: reduceState }); diff --git a/packages/gitbook-plugin/README.md b/packages/gitbook-plugin/README.md index a6ded9e..64f2ce9 100644 --- a/packages/gitbook-plugin/README.md +++ b/packages/gitbook-plugin/README.md @@ -1,3 +1 @@ -# `gitbook-plugin` - -CLI utility to build and test plugins. +See [GitBook: Create a plugin](toolchain.gitbook.com/api/). |