2019-04-03 07:56:58 +02:00
|
|
|
// @flow
|
|
|
|
import * as React from 'react';
|
|
|
|
import remark from 'remark';
|
2019-06-10 22:16:01 +02:00
|
|
|
import remarkAttr from 'remark-attr';
|
2019-06-09 08:57:51 +02:00
|
|
|
import remarkStrip from 'strip-markdown';
|
2019-04-03 07:56:58 +02:00
|
|
|
import remarkEmoji from 'remark-emoji';
|
2019-05-30 22:51:23 +02:00
|
|
|
import reactRenderer from 'remark-react';
|
2019-04-03 07:56:58 +02:00
|
|
|
import ExternalLink from 'component/externalLink';
|
|
|
|
import defaultSchema from 'hast-util-sanitize/lib/github.json';
|
2019-06-10 08:20:40 +02:00
|
|
|
import { formatedLinks, inlineLinks } from 'util/remark-lbry';
|
2020-01-04 03:35:06 +01:00
|
|
|
import { Link } from 'react-router-dom';
|
|
|
|
import { formatLbryUrlForWeb } from 'util/url';
|
2019-04-03 07:56:58 +02:00
|
|
|
|
2019-06-09 08:57:51 +02:00
|
|
|
type SimpleTextProps = {
|
|
|
|
children?: React.Node,
|
2019-04-03 07:56:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
type SimpleLinkProps = {
|
|
|
|
href?: string,
|
|
|
|
title?: string,
|
|
|
|
children?: React.Node,
|
|
|
|
};
|
|
|
|
|
2019-06-09 08:57:51 +02:00
|
|
|
type MarkdownProps = {
|
|
|
|
strip?: boolean,
|
|
|
|
content: ?string,
|
|
|
|
promptLinks?: boolean,
|
|
|
|
};
|
|
|
|
|
|
|
|
const SimpleText = (props: SimpleTextProps) => {
|
|
|
|
return <span>{props.children}</span>;
|
|
|
|
};
|
|
|
|
|
2019-04-03 07:56:58 +02:00
|
|
|
const SimpleLink = (props: SimpleLinkProps) => {
|
2020-01-04 03:35:06 +01:00
|
|
|
const { title, children } = props;
|
|
|
|
let { href } = props;
|
2020-02-03 23:29:22 +01:00
|
|
|
if (IS_WEB && href && href.startsWith('lbry://')) {
|
2020-01-04 03:35:06 +01:00
|
|
|
href = formatLbryUrlForWeb(href);
|
2020-01-04 04:36:27 +01:00
|
|
|
// using Link after formatLbryUrl to handle "/" vs "#/"
|
2020-01-04 03:35:06 +01:00
|
|
|
// for web and desktop scenarios respectively
|
|
|
|
return (
|
|
|
|
<Link
|
|
|
|
title={title}
|
|
|
|
to={href}
|
|
|
|
onClick={e => {
|
|
|
|
e.stopPropagation();
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{children}
|
|
|
|
</Link>
|
|
|
|
);
|
|
|
|
}
|
2019-04-03 07:56:58 +02:00
|
|
|
return (
|
|
|
|
<a href={href} title={title}>
|
|
|
|
{children}
|
|
|
|
</a>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Use github sanitation schema
|
|
|
|
const schema = { ...defaultSchema };
|
|
|
|
|
|
|
|
// Extend sanitation schema to support lbry protocol
|
2019-05-30 22:51:23 +02:00
|
|
|
schema.protocols.href.push('lbry');
|
2019-06-13 09:18:30 +02:00
|
|
|
schema.attributes.a.push('embed');
|
2019-04-03 07:56:58 +02:00
|
|
|
|
|
|
|
const MarkdownPreview = (props: MarkdownProps) => {
|
2019-06-09 08:57:51 +02:00
|
|
|
const { content, strip, promptLinks } = props;
|
|
|
|
|
|
|
|
const remarkOptions: Object = {
|
2019-04-03 07:56:58 +02:00
|
|
|
sanitize: schema,
|
2019-06-09 08:57:51 +02:00
|
|
|
fragment: React.Fragment,
|
2019-04-03 07:56:58 +02:00
|
|
|
remarkReactComponents: {
|
|
|
|
a: promptLinks ? ExternalLink : SimpleLink,
|
2019-06-09 08:57:51 +02:00
|
|
|
// Workaraund of remarkOptions.Fragment
|
|
|
|
div: React.Fragment,
|
2019-04-03 07:56:58 +02:00
|
|
|
},
|
|
|
|
};
|
2019-06-09 08:57:51 +02:00
|
|
|
|
2019-06-10 22:16:01 +02:00
|
|
|
const remarkAttrOpts = {
|
|
|
|
scope: 'extended',
|
|
|
|
elements: ['link'],
|
2019-06-13 09:18:30 +02:00
|
|
|
extend: { link: ['embed'] },
|
2019-06-12 04:22:21 +02:00
|
|
|
defaultValue: true,
|
2019-06-10 22:16:01 +02:00
|
|
|
};
|
|
|
|
|
2019-06-09 08:57:51 +02:00
|
|
|
// Strip all content and just render text
|
|
|
|
if (strip) {
|
|
|
|
// Remove new lines and extra space
|
|
|
|
remarkOptions.remarkReactComponents.p = SimpleText;
|
|
|
|
return (
|
|
|
|
<span className="markdown-preview">
|
|
|
|
{
|
|
|
|
remark()
|
|
|
|
.use(remarkStrip)
|
|
|
|
.use(reactRenderer, remarkOptions)
|
|
|
|
.processSync(content).contents
|
|
|
|
}
|
|
|
|
</span>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-04-03 07:56:58 +02:00
|
|
|
return (
|
|
|
|
<div className="markdown-preview">
|
|
|
|
{
|
|
|
|
remark()
|
2019-06-10 22:16:01 +02:00
|
|
|
.use(remarkAttr, remarkAttrOpts)
|
2019-06-10 08:20:40 +02:00
|
|
|
// Remark plugins for lbry urls
|
|
|
|
// Note: The order is important
|
|
|
|
.use(formatedLinks)
|
|
|
|
.use(inlineLinks)
|
|
|
|
// Emojis
|
2019-04-03 07:56:58 +02:00
|
|
|
.use(remarkEmoji)
|
|
|
|
.use(reactRenderer, remarkOptions)
|
|
|
|
.processSync(content).contents
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default MarkdownPreview;
|