diff --git a/frontend/components/Document/Document.js b/frontend/components/Document/Document.js index 9902fdfa..1bfd9e7c 100644 --- a/frontend/components/Document/Document.js +++ b/frontend/components/Document/Document.js @@ -3,48 +3,14 @@ import { toJS } from 'mobx'; import { observer } from 'mobx-react'; import PublishingInfo from 'components/PublishingInfo'; +import DocumentHtml from './components/DocumentHtml'; import styles from './Document.scss'; -@observer -class DocumentHtml extends React.Component { - static propTypes = { - html: PropTypes.string.isRequired, - } - - componentDidMount = () => { - this.setExternalLinks(); - } - - componentDidUpdate = () => { - this.setExternalLinks(); - } - - setExternalLinks = () => { - const links = this.refs.content.querySelectorAll('a'); - links.forEach(link => { - if (link.hostname !== window.location.hostname) { - link.target = '_blank'; // eslint-disable-line no-param-reassign - } - }); - } - - render() { - return ( -
- ); - } -} - @observer class Document extends React.Component { static propTypes = { - document: React.PropTypes.object.isRequired, + document: PropTypes.object.isRequired, } render() { @@ -64,6 +30,3 @@ class Document extends React.Component { } export default Document; -export { - DocumentHtml, -}; diff --git a/frontend/components/Document/Document.scss b/frontend/components/Document/Document.scss index a7cbd244..a16145a9 100644 --- a/frontend/components/Document/Document.scss +++ b/frontend/components/Document/Document.scss @@ -4,87 +4,3 @@ width: 100%; padding: 20px 20px 40px 20px; } - -.document { - h1, h2, h3, h4, h5, h6 { - :global { - .anchor { - visibility: hidden; - color: $gray; - } - } - - &:hover { - :global { - .anchor { - visibility: visible; - } - } - } - } - - ul { - padding-left: 1.5em; - - ul { - margin: 0; - } - } - - // pre { - // box-shadow: 1px 1px 1px #f5f5f5; - // } - - blockquote { - font-style: italic; - border-left: 2px solid $lightGray; - padding-left: 0.8em; - } - - table { - width: 100%; - overflow: auto; - display: block; - border-spacing: 0; - border-collapse: collapse; - - thead, tbody { - width: 100%; - } - - thead { - tr { - border-bottom: 2px solid $lightGray; - } - } - - tbody { - tr { - border-bottom: 1px solid $lightGray; - } - } - - tr { - background-color: #fff; - - // &:nth-child(2n) { - // background-color: #f8f8f8; - // } - } - - th, td { - text-align: left; - border: 1px 0 solid $lightGray; - padding: 5px 20px 5px 0; - - &:last-child { - padding-right: 0; - width: 100%; - } - } - - th { - font-weight: bold; - } - } -} diff --git a/frontend/components/Document/components/DocumentHtml/DocumentHtml.js b/frontend/components/Document/components/DocumentHtml/DocumentHtml.js new file mode 100644 index 00000000..7f0a0a1f --- /dev/null +++ b/frontend/components/Document/components/DocumentHtml/DocumentHtml.js @@ -0,0 +1,40 @@ +import React, { PropTypes } from 'react'; +import ReactDOM from 'react-dom'; +import { observer } from 'mobx-react'; + +import styles from './DocumentHtml.scss'; + +@observer +class DocumentHtml extends React.Component { + static propTypes = { + html: PropTypes.string.isRequired, + } + + componentDidMount = () => { + this.setExternalLinks(); + } + + componentDidUpdate = () => { + this.setExternalLinks(); + } + + setExternalLinks = () => { + const links = ReactDOM.findDOMNode(this).querySelectorAll('a'); + links.forEach(link => { + if (link.hostname !== window.location.hostname) { + link.target = '_blank'; // eslint-disable-line no-param-reassign + } + }); + } + + render() { + return ( +
+ ); + } +} + +export default DocumentHtml; diff --git a/frontend/components/Document/components/DocumentHtml/DocumentHtml.scss b/frontend/components/Document/components/DocumentHtml/DocumentHtml.scss new file mode 100644 index 00000000..e13d1ab3 --- /dev/null +++ b/frontend/components/Document/components/DocumentHtml/DocumentHtml.scss @@ -0,0 +1,85 @@ +@import '~styles/constants.scss'; + +.document { + h1, h2, h3, h4, h5, h6 { + :global { + .anchor { + visibility: hidden; + color: $gray; + } + } + + &:hover { + :global { + .anchor { + visibility: visible; + } + } + } + } + + ul { + padding-left: 1.5em; + + ul { + margin: 0; + } + } + + // pre { + // box-shadow: 1px 1px 1px #f5f5f5; + // } + + blockquote { + font-style: italic; + border-left: 2px solid $lightGray; + padding-left: 0.8em; + } + + table { + width: 100%; + overflow: auto; + display: block; + border-spacing: 0; + border-collapse: collapse; + + thead, tbody { + width: 100%; + } + + thead { + tr { + border-bottom: 2px solid $lightGray; + } + } + + tbody { + tr { + border-bottom: 1px solid $lightGray; + } + } + + tr { + background-color: #fff; + + // &:nth-child(2n) { + // background-color: #f8f8f8; + // } + } + + th, td { + text-align: left; + border: 1px 0 solid $lightGray; + padding: 5px 20px 5px 0; + + &:last-child { + padding-right: 0; + width: 100%; + } + } + + th { + font-weight: bold; + } + } +} diff --git a/frontend/components/Document/components/DocumentHtml/DocumentHtml.test.js b/frontend/components/Document/components/DocumentHtml/DocumentHtml.test.js new file mode 100644 index 00000000..5295115d --- /dev/null +++ b/frontend/components/Document/components/DocumentHtml/DocumentHtml.test.js @@ -0,0 +1,20 @@ +/* eslint-disable */ +import React from 'react'; +import ReactDOM from 'react-dom'; +import DocumentHtml from './DocumentHtml'; +import { shallow } from 'enzyme'; + +const testHtml = ` +

test document

+

Hello! internal link

+

Aliens external link

+`; + +test('renders', () => { + const wrapper = shallow( + + ); + expect(wrapper.find('.document').length).toBe(1); +}); diff --git a/frontend/components/Document/components/DocumentHtml/index.js b/frontend/components/Document/components/DocumentHtml/index.js new file mode 100644 index 00000000..8c1e31ed --- /dev/null +++ b/frontend/components/Document/components/DocumentHtml/index.js @@ -0,0 +1,2 @@ +import DocumentHtml from './DocumentHtml'; +export default DocumentHtml; diff --git a/frontend/components/Document/index.js b/frontend/components/Document/index.js index a477d1b8..a31bbbc2 100644 --- a/frontend/components/Document/index.js +++ b/frontend/components/Document/index.js @@ -1,4 +1,5 @@ -import Document, { DocumentHtml } from './Document'; +import Document from './Document'; +import DocumentHtml from './components/DocumentHtml'; export default Document; export { diff --git a/frontend/scenes/Flatpage/Flatpage.js b/frontend/scenes/Flatpage/Flatpage.js index 47c16e8e..6d0afbec 100644 --- a/frontend/scenes/Flatpage/Flatpage.js +++ b/frontend/scenes/Flatpage/Flatpage.js @@ -10,7 +10,7 @@ import { convertToMarkdown } from 'utils/markdown'; @observer class Flatpage extends React.Component { static propTypes = { - route: PropTypes.object.isRequired, + route: PropTypes.object, } render() { diff --git a/package.json b/package.json index 2320c064..5f0e3ad6 100644 --- a/package.json +++ b/package.json @@ -150,6 +150,7 @@ }, "devDependencies": { "babel-jest": "^15.0.0", + "enzyme": "^2.4.1", "fetch-test-server": "^1.1.0", "fsevents": "1.0.14", "identity-obj-proxy": "^3.0.0", @@ -159,6 +160,7 @@ "koa-webpack-hot-middleware": "1.0.3", "node-dev": "3.1.0", "nodemon": "1.9.1", + "react-addons-test-utils": "^15.3.1", "react-test-renderer": "^15.3.1" } }