Add Markdown component to render markdown
Summary: Adds a Markdown component to the component library. The react-markdown library doesn't work out of the box because elements it outputs don't have any styles, e.g. h1, h2, p, em, etc. So I've added a custom renderer to give styles to each of these that workplace markdown uses. The only one I haven't done at the moment that I'm aware of is numbered-lists. There's probably a way to get back the original styling of these elements so we don't need a custom renderer, but this works for now, and also allows us to customise their appearance. Reviewed By: passy Differential Revision: D18533085 fbshipit-source-id: a4332a11d34d577a6300074e4dde126362d46a6b
This commit is contained in:
committed by
Facebook Github Bot
parent
6c4e687d63
commit
352d9c82cb
101
src/ui/components/Markdown.tsx
Normal file
101
src/ui/components/Markdown.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
*/
|
||||
|
||||
import React, {PureComponent, RefObject} from 'react';
|
||||
import styled from 'react-emotion';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {colors} from './colors';
|
||||
import {shell} from 'electron';
|
||||
|
||||
const Row = styled('div')({
|
||||
marginTop: 5,
|
||||
marginBottom: 5,
|
||||
});
|
||||
const Heading = styled('div')((props: {level: number}) => ({
|
||||
fontSize: Math.max(10, 20 - (props.level - 1) * 4),
|
||||
marginBottom: 10,
|
||||
fontWeight: 'bold',
|
||||
}));
|
||||
const ListItem = styled('li')({
|
||||
'list-style-type': 'circle',
|
||||
'list-style-position': 'inside',
|
||||
marginLeft: 10,
|
||||
});
|
||||
const Strong = styled('span')({
|
||||
fontWeight: 'bold',
|
||||
});
|
||||
const Emphasis = styled('span')({
|
||||
fontStyle: 'italic',
|
||||
});
|
||||
const Quote = styled(Row)({
|
||||
padding: 10,
|
||||
backgroundColor: '#f1f2f3',
|
||||
});
|
||||
const Code = styled('span')({
|
||||
fontFamily: '"Courier New", Courier, monospace',
|
||||
backgroundColor: '#f1f2f3',
|
||||
});
|
||||
const Pre = styled(Row)({
|
||||
padding: 10,
|
||||
backgroundColor: '#f1f2f3',
|
||||
});
|
||||
class CodeBlock extends PureComponent<{value: string; language: string}> {
|
||||
render() {
|
||||
return (
|
||||
<Pre>
|
||||
<Code>{this.props.value}</Code>
|
||||
</Pre>
|
||||
);
|
||||
}
|
||||
}
|
||||
const Link = styled('span')({
|
||||
color: colors.blue,
|
||||
textDecoration: 'underline',
|
||||
});
|
||||
class LinkReference extends PureComponent<{href: string}> {
|
||||
render() {
|
||||
return (
|
||||
<Link onClick={() => shell.openExternal(this.props.href)}>
|
||||
{this.props.children}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class Markdown extends PureComponent<{
|
||||
source: string;
|
||||
}> {
|
||||
containerRef: RefObject<HTMLDivElement> = React.createRef();
|
||||
|
||||
componentDidMount() {
|
||||
ReactDOM.render(
|
||||
<ReactMarkdown
|
||||
source={this.props.source}
|
||||
renderers={{
|
||||
heading: Heading,
|
||||
listItem: ListItem,
|
||||
paragraph: Row,
|
||||
strong: Strong,
|
||||
emphasis: Emphasis,
|
||||
inlineCode: Code,
|
||||
code: CodeBlock,
|
||||
blockquote: Quote,
|
||||
link: LinkReference,
|
||||
linkReference: LinkReference,
|
||||
}}
|
||||
/>,
|
||||
this.containerRef.current,
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div ref={this.containerRef}></div>;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user