Skip to content

Commit

Permalink
Use Link component when rendering markdown links
Browse files Browse the repository at this point in the history
  • Loading branch information
kmjennison committed Oct 22, 2021
1 parent 02599d8 commit 74e9daa
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 16 deletions.
5 changes: 1 addition & 4 deletions __mocks__/next/link.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'

const MockNextLink = ({ children }) => (
<div data-test-id="mock-next-js-link">{children}</div>
)
const MockNextLink = ({ children }) => children
MockNextLink.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
Expand Down
30 changes: 24 additions & 6 deletions src/components/Markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,37 @@ import remarkRehype from 'remark-rehype'
import rehypeSanitize, { defaultSchema } from 'rehype-sanitize'
import rehypeReact from 'rehype-react'
import Typography from '@material-ui/core/Typography'
import Link from 'src/components/Link'
import { makeStyles } from '@material-ui/core/styles'

const schema = defaultSchema
const useStyles = makeStyles((theme) => ({
anchor: {
color: theme.palette.primary.main,
textDecoration: 'underline',
},
}))

const MarkdownLink = ({ href, ...otherProps }) => {
const cx = useStyles()
return (
<Link target="_blank" to={href} className={cx.anchor} {...otherProps} />
)
}
MarkdownLink.displayName = 'MarkdownLink'
MarkdownLink.propTypes = {
href: PropTypes.string,
}
MarkdownLink.defaultProps = {
href: undefined,
}

// https://github.com/remarkjs/remark
const processor = unified()
.use(remarkParse)
.use(remarkRehype)

// https://github.com/rehypejs/rehype-sanitize#use
.use(rehypeSanitize, schema)
.use(rehypeSanitize, defaultSchema)
.use(rehypeReact, {
createElement: React.createElement,
components: {
Expand All @@ -33,10 +54,7 @@ const processor = unified()
h5: (props) => <Typography {...props} variant="body1" gutterBottom />,
h6: (props) => <Typography {...props} variant="caption" />,
p: (props) => <Typography {...props} variant="body2" paragraph />,

// Anchor will have content when rendered.
// eslint-disable-next-line jsx-a11y/anchor-has-content
a: (props) => <a target="_blank" {...props} />,
a: MarkdownLink,
},
})

Expand Down
14 changes: 9 additions & 5 deletions src/components/__mocks__/Link.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import React from 'react'
import PropTypes from 'prop-types'

const MockLink = ({ children }) => (
<div data-test-id="mock-link">
<a>{children}</a>
</div>
const MockLink = ({ children, target, to }) => (
<a data-test-id="mock-link" target={target} href={to}>
{children}
</a>
)

MockLink.propTypes = {
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node,
]).isRequired,
target: PropTypes.string,
to: PropTypes.string.isRequired,
}

MockLink.defaultProps = {}
MockLink.defaultProps = {
target: undefined,
}

export default MockLink
17 changes: 17 additions & 0 deletions src/components/__tests__/Markdown.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import path from 'path'
import React from 'react'
import { mount } from 'enzyme'

jest.mock('src/components/Link')

const getMockProps = () => ({
children: '# Hi there!',
})
Expand Down Expand Up @@ -59,6 +61,21 @@ describe('Markdown component', () => {
expect(wrapper.html()).toEqual(expectedHTML)
})

it('renders a link to expected html', () => {
const Markdown = require('src/components/Markdown').default
const mockProps = {
...getMockProps(),
children: '[i am a link](https://example.com)',
}
jest.spyOn(console, 'error').mockImplementation(() => {})
const wrapper = mount(<Markdown {...mockProps} />)

// Uses mock Link component
const expectedHTML =
'<div><p class="MuiTypography-root MuiTypography-body2 MuiTypography-paragraph"><a data-test-id="mock-link" target="_blank" href="https://example.com">i am a link</a></p></div>'
expect(wrapper.html()).toEqual(expectedHTML)
})

it('does not render script tags', () => {
const Markdown = require('src/components/Markdown').default
const mockProps = {
Expand Down
2 changes: 1 addition & 1 deletion src/utils/testHelpers/testHTML-A.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ <h6 class="MuiTypography-root MuiTypography-h6 MuiTypography-gutterBottom">Markd
<span class="MuiTypography-root MuiTypography-caption">Markdown h6 maps to Typography caption</span>
<p class="MuiTypography-root MuiTypography-body2 MuiTypography-paragraph">Our humble paragraph uses Typography body2. And here is...</p>
<p class="MuiTypography-root MuiTypography-body2 MuiTypography-paragraph">... another paragraph!</p>
<p class="MuiTypography-root MuiTypography-body2 MuiTypography-paragraph">And a <strong>bold</strong>, then <em>italicized</em>, word with a <a target="_blank" href="https://example.com">link here</a>.</p></div>
<p class="MuiTypography-root MuiTypography-body2 MuiTypography-paragraph">And a <strong>bold</strong>, then <em>italicized</em>, word with a <a data-test-id="mock-link" target="_blank" href="https://example.com">link here</a>.</p></div>

0 comments on commit 74e9daa

Please sign in to comment.