summaryrefslogtreecommitdiffstats
path: root/packages/gitbook-plugin-theme-default/src/components/Body.js
diff options
context:
space:
mode:
authorSamy Pessé <samypesse@gmail.com>2016-12-22 10:18:38 +0100
committerGitHub <noreply@github.com>2016-12-22 10:18:38 +0100
commit194ebc3da9641ff96f083f9d8ab43c2d27944f9a (patch)
treec50988f32ccf18df93ae7ab40be78e9459642818 /packages/gitbook-plugin-theme-default/src/components/Body.js
parent64ccb6b00b4b63fa0e516d4e35351275b34f8c07 (diff)
parent16af264360e48e8a833e9efa9ab8d194574dbc70 (diff)
downloadgitbook-194ebc3da9641ff96f083f9d8ab43c2d27944f9a.zip
gitbook-194ebc3da9641ff96f083f9d8ab43c2d27944f9a.tar.gz
gitbook-194ebc3da9641ff96f083f9d8ab43c2d27944f9a.tar.bz2
Merge pull request #1543 from GitbookIO/dream
React for rendering website with plugins
Diffstat (limited to 'packages/gitbook-plugin-theme-default/src/components/Body.js')
-rw-r--r--packages/gitbook-plugin-theme-default/src/components/Body.js121
1 files changed, 121 insertions, 0 deletions
diff --git a/packages/gitbook-plugin-theme-default/src/components/Body.js b/packages/gitbook-plugin-theme-default/src/components/Body.js
new file mode 100644
index 0000000..c61a2f3
--- /dev/null
+++ b/packages/gitbook-plugin-theme-default/src/components/Body.js
@@ -0,0 +1,121 @@
+const debounce = require('debounce');
+const GitBook = require('gitbook-core');
+const { React } = GitBook;
+
+const Page = require('./Page');
+const Toolbar = require('./Toolbar');
+
+const HEADINGS_SELECTOR = 'h1[id],h2[id],h3[id],h4[id]';
+
+/**
+ * Get offset of an element relative to a parent container.
+ * @param {DOMElement} container
+ * @param {DOMElement} element
+ * @return {Number} offset
+ */
+function getOffset(container, element, type = 'Top') {
+ const parent = element.parentElement;
+ let base = 0;
+
+ if (parent != container) {
+ base = getOffset(container, parent, type);
+ }
+
+ return base + element[`offset${type}`];
+}
+
+/**
+ * Find the current heading anchor for a scroll position.
+ * @param {DOMElement} container
+ * @param {Number} top
+ * @return {String}
+ */
+function getHeadingID(container, top) {
+ let id;
+ const headings = container.querySelectorAll(HEADINGS_SELECTOR);
+
+ headings.forEach(heading => {
+ if (id) {
+ return;
+ }
+
+ const offset = getOffset(container, heading);
+
+ if (offset > top) {
+ id = heading.getAttribute('id');
+ }
+ });
+
+ return id;
+}
+
+const Body = React.createClass({
+ propTypes: {
+ page: GitBook.PropTypes.Page,
+ readme: GitBook.PropTypes.Readme,
+ history: GitBook.PropTypes.History,
+ updateURI: React.PropTypes.func
+ },
+
+ getInitialState() {
+ this.debouncedOnScroll = debounce(this.onScroll, 300);
+ return {};
+ },
+
+ /**
+ * User is scrolling the page, update the location with current section's ID.
+ */
+ onScroll() {
+ const { scrollContainer } = this;
+ const { history, updateURI } = this.props;
+ const { location } = history;
+
+ // Find the id matching the current scroll position
+ const hash = getHeadingID(scrollContainer, scrollContainer.scrollTop);
+
+ // Update url if changed
+ if (hash !== location.hash) {
+ updateURI(location.merge({ hash }));
+ }
+ },
+
+ /**
+ * Component has been updated with a new location,
+ * scroll to the right anchor.
+ */
+ componentDidUpdate() {
+
+ },
+
+ render() {
+ const { page, readme } = this.props;
+
+ return (
+ <GitBook.InjectedComponent matching={{ role: 'body:wrapper' }}>
+ <div
+ className="Body page-wrapper"
+ onScroll={this.debouncedOnScroll}
+ ref={div => this.scrollContainer = div}
+ >
+ <GitBook.InjectedComponent matching={{ role: 'toolbar:wrapper' }}>
+ <Toolbar title={page.title} readme={readme} />
+ </GitBook.InjectedComponent>
+ <GitBook.InjectedComponent matching={{ role: 'page:wrapper' }}>
+ <Page page={page} />
+ </GitBook.InjectedComponent>
+ </div>
+ </GitBook.InjectedComponent>
+ );
+ }
+});
+
+module.exports = GitBook.connect(Body,
+ () => {
+ return {};
+ },
+ ({ History }, dispatch) => {
+ return {
+ updateURI: (location) => dispatch(History.replace(location))
+ };
+ }
+);